Pymel: Как мне закрыть For l oop после удаления нулевых групп? - PullRequest
0 голосов
/ 27 февраля 2020

Пока я продолжаю изучать For Loops: я столкнулся с некоторыми досадными ошибками. Проблема в том, что скрипт делает именно то, что я хочу. Он удаляет группы null под демонстрационными соединениями, но в отличие от других циклов, которые я сделал для переименования, который можно закрыть с помощью флага преобразования в команде cmds.ls: cmds.listRelatives не позволяет закрывать флаг преобразования Л oop. Вы запускаете скрипт, просто нажимая Build Examples, затем нажимая Delete Waste Groups

Я пробовал каждый флаг в соответствии с документацией Maya: но, кажется, ничто не закрывает l oop. Я не знаю, нужна ли мне другая переменная или комбинация некоторых флагов: или я использую неправильный тип формулировки: но в идеале я хотел бы, чтобы этот скрипт просто закрывал l oop, поэтому я не получаю ошибка Error: No object matches name: curve

'''
import DS_wasteGroup_cleanerDemo
reload (DS_wasteGroup_cleanerDemo)
DS_wasteGroup_cleanerDemo.gui()
'''

import re
import maya.cmds as cmds
import maya.mel as mel

if cmds.window("renameWin", exists =True):
    cmds.deleteUI("renameWin", window = True)

myWindow = cmds.window("renameWin",t='DS_wasteGroup_cleanerDemo',w=200, h=500, toolbox=True)
column = cmds.columnLayout(adj=True)

def gui():

    cmds.button( label="Build Examples", c = buildExamples)
    cmds.separator( w=200, h=3)
    cmds.button( label="Delete Waste Groups", c = deleteWasteGrp)
    cmds.separator( w=200, h=9)

    cmds.setParent('..')
    cmds.showWindow(myWindow)

def buildExamples(*args):

    cmds.group(n='exampleGroup1',world=True,empty=True)
    cmds.joint(n='demoJoint1')
    cmds.group(n='curve1',world=True,empty=True)
    cmds.parent('curve1','demoJoint1')

    cmds.joint(n='demoJoint2')
    cmds.parent('demoJoint2','exampleGroup1')
    cmds.group(n='curve2',world=True,empty=True)
    cmds.parent('curve2','demoJoint2')

    cmds.joint(n='demoJoint3')
    cmds.parent('demoJoint3','exampleGroup1')
    cmds.group(n='curve3',world=True,empty=True)
    cmds.parent('curve3','demoJoint3')

    cmds.joint(n='demoJoint4')
    cmds.parent('demoJoint4','exampleGroup1')
    cmds.group(n='curve4',world=True,empty=True)
    cmds.parent('curve4','demoJoint4')

    cmds.joint(n='demoJoint5')
    cmds.parent('demoJoint5','exampleGroup1')
    cmds.group(n='curve5',world=True,empty=True)
    cmds.parent('curve5','demoJoint5')


def deleteWasteGrp(*args):
    grpList = cmds.listRelatives('demoJoint*',p=True,f=True)
    for name in grpList:
        print(grpList)
        cmds.delete('curve*')

Мои извинения, если я публикую простые вопросы. Я пишу Python скрипты, чтобы автоматизировать самые утомительные задачи в фальсификации: но мои знания только промежуточные. Я хочу узнать больше python, чтобы мои сценарии не были такими неуклюжими и грубыми, а также тот факт, что они мне нужны, чтобы они были более адаптируемыми к различным типам персонажей: поэтому любые ресурсы, которые делают все это глупыми, также будут оценены. Спасибо за вашу помощь.

Ответы [ 3 ]

1 голос
/ 27 февраля 2020

Ошибка правильная, поскольку при первом выполнении for для l oop все объекты «кривой» удаляются, а затем на следующей итерации та же команда не находит объекты кривой, поскольку они уже удалены. Если вы поместите команду удаления вне поля для l oop, ошибка должна исчезнуть.

0 голосов
/ 28 февраля 2020

Честно говоря, я бы использовал совершенно другой подход, поскольку вы жестко программируете все, что может легко привести к катастрофе. Когда я имею в виду жесткий код, я имею в виду, что вы пытаетесь родить, скажем, "demoJoint2" объекта. Это плохо, потому что почему вы предполагаете, что "demoJoint2" вообще существует? Если вы создаете объект с указанным c именем, которое уже существует, Maya автоматически переименует новый объект, и теперь вы сразу же ссылаетесь на неправильный объект! Вместо этого, когда вы создаете свои объекты, фиксируйте их имена в переменной, а затем работайте с этим, иначе вы будете постоянно стрелять себе в ногу.

Вот тот же сценарий с подходом, который я бы использовал вместо этого:

import maya.cmds as cmds


def gui():
    if cmds.window("renameWin", exists=True):
        cmds.deleteUI("renameWin", window=True)

    myWindow = cmds.window("renameWin", t="DS_wasteGroup_cleanerDemo", w=200, h=500, toolbox=True)
    column = cmds.columnLayout(adj=True)

    cmds.button(label="Build Examples", c=buildExamples)
    cmds.separator(w=200, h=3)
    cmds.button(label="Delete Waste Groups", c=deleteWasteGrp)
    cmds.separator(w=200, h=9)

    cmds.setParent("..")
    cmds.showWindow(myWindow)


def buildExamples(*args):
    root = cmds.group(n="exampleGroup1", world=True, empty=True)

    for i in range(5):  # Loop to the amount of joints you want to create.
        jnt = cmds.createNode("joint", name="demoJoint" + str(i + 1))  # Use `i` to help name the object.
        jnt = cmds.parent(jnt, root)[0]  # Parenting changes its long name, so recapture the joint in a variable.
        crv = cmds.group(n="curve" + str(i + 1), world=True, empty=True)  # Create empty group.
        cmds.parent(crv, jnt)  # Parent curve to joint.


def deleteWasteGrp(*args):
    jnts = cmds.ls("demoJoint*", long=True, type="joint")  # Get all `demoJoints`.
    children = cmds.listRelatives(jnts, f=True, children=True, type="transform") or []  # Get all of their children, and only get transform types.
    curves = [obj for obj in children if obj.split("|")[-1].startswith("curve")]  # Don't assume we got the right objects. Run a final loop to collect any object that starts with `curve`. Need to use split as we're looping through long names but need to check its short name.
    if curves:  # `cmds.delete` will error if this list is empty, so don't assume.
        cmds.delete(curves)  # Delete all curves at once.


gui()

Теперь я могу нажимать на кнопку сборки сколько угодно без проблем и удалять все кривые при нажатии кнопки удаления.

Еще несколько примечаний:

Обратите внимание на buildExamples Я использую al oop для создания всех объектов вместо повторного использования избыточного кода, который делает то же самое. Вы могли бы даже иметь спинбокс в вашем gui, который определяет, сколько соединений он создает сейчас, где, как раньше, это было невозможно, потому что счет был жестко запрограммирован.

cmds.listRelatives делает * У 1017 * есть способ фильтровать объекты по преобразованиям, установив параметр type="transform". Фактически, вы увидите, что многие команды имеют один и тот же параметр (снова начните проверять документы).

cmds.listRelatives('demoJoint*',p=True,f=True) захватывал родителя соединения, а не его потомков. Документы ясно утверждают это.

Запуск cmds.delete('curve*') приведет к удалению ALL объектов с именами, которые начинаются с кривой, а поскольку вы запускаете это в al oop, он пытается сделайте это несколько раз.

maya.cmds это не pymel. Существует целый отдельный модуль, называемый pymel.

Если вы не уверены в каких-либо частях кода, попробуйте добавить оператор print, чтобы увидеть, что он делает.

0 голосов
/ 28 февраля 2020

Я чувствую, что вы идете по поводу всего этого процесса немного неправильно, и я хотел бы уточнить, если вам интересно, но сейчас вот исправление для вашей ситуации l oop:

def deleteWasteGrp(*args):    
    curveList = cmds.ls('curve*',transforms=True)
    try:
        cmds.delete(curveList)
        print('Deleted the following objects: {}'.format(curveList))
    except Exception as e:
        cmds.warning('Cleanup failed: {}'.format(e))

Метод cmds.delete принимает параметр списка, который в вашем случае является самым простым способом выполнить работу. Имейте в виду, что когда вы удаляете родительский объект, вы также удаляете его дочерние объекты, поэтому в зависимости от ваших обстоятельств удаление объектов может зависеть от порядка c.

Бросать любые вызовы с "вероятностью сбоя" в попытке / Кроме того, предложение, как правило, является хорошей идеей, поскольку позволяет корректно обработать ошибку. Однако будьте осторожны, чтобы не подавлять его и просто двигаться дальше - вам по крайней мере нужно адекватно предупредить пользователя.

Наконец, ваш метод buildExamples, скорее всего, потерпит неудачу, если вы запустите его больше, чем один раз. Потому что вы обращаетесь к объектам строковыми литералами (жестко закодированными именами) вместо того, чтобы отслеживать их фактические имена (и полный путь). Скорее всего, в конечном итоге вы увидите эту ошибку:

# Error: ValueError: file <maya console> line ??: More than one object matches name: demoJoint1 # 

Редактировать: некоторые уточнения по запросу

Команды cmds.group и cmds.joint возвращают строковое значение, указывающее фактическое имя созданного объекта (в режиме создания). Обычно хорошей идеей является сохранение этого значения на тот случай, если Maya решит назвать ваш объект немного иначе, чем вы ожидаете, обычно, когда есть наименование cla sh. Например:

print cmds.group(name='test', world=True, empty=True)
# Returns: test

print cmds.group(name='test', world=True, empty=True)
# Returns: test1

Пример того, как захватывать имена объектов при их создании. Я объединил ваши пять одинаковых (i sh) вызовов для создания соединений и кривых в этом l oop:

import maya.cmds as cmds

topGroupName = 'exampleGroup'
actualTopGroupName = None

# Create top level group
actualTopGroupName = cmds.group(n=topGroupName, world=True, empty=True)

# Loop through 5 times and do the following:
for i in range(5):
    # PS: hash character in name indicates "next available number"
    cmds.select(clear=True)
    jnt = cmds.joint(n='demoJoint#') 
    crv = cmds.group(n='curve#',world=True,empty=True)
    cmds.parent(crv, jnt)
    cmds.parent(jnt, actualTopGroupName)

Пример того, как сузить, какие объекты нужно искать с помощью cmds.ls :

topGroupName = 'exampleGroup'
print cmds.ls('|{}*|*|curve*'.format(topGroupName)) 
# Returns: [u'curve1', u'curve2', u'curve3', u'curve4', u'curve5']

# The string .format() expression is just a dynamic way of writing this:
# |exampleGroup*|*|curve*

Вертикальные каналы (|) указывают уровни в иерархии, подобно тому, как косые черты (/) работают в URL. А звездочки / подстановочные знаки (*) обозначают «любой символ или ни одного».

Надеюсь, это немного поможет вам на вашем пути.

...