Maya Python: Соедините три соединительные цепи через Tripple List - PullRequest
0 голосов
/ 01 мая 2020

Я пытался создать собственный скрипт авторизации, когда дело доходит до конечностей IKFK на основе метода Энтони Уорда, здесь: https://www.youtube.com/watch?v=uzHn_4ByyjY&t=10s

Пока что это идет очень хорошо: но я столкнулся с SpeedBump. Принцип работы этого сценария прост:

  1. Выберите цепь соединений с любым количеством соединений и нажмите «Переименовать цепь соединений»

  2. Установить сторону префикс и префикс имени лимба, который вы хотите встроить в текстовые поля, например: текстовое поле 1: «левое» текстовое поле 2: «нога»

  3. In c From end ползунок определяет положение переключателя IKFK на соединительной цепи. Ноль ставит его в конце, каждый шаг вверх сдвигает его вверх по объединенной цепи.

  4. Выберите root вашей объединенной цепи и нажмите «Шаблон сборки»

Где сценарий икает - шаг 5. Я попытался создать тройной список, чтобы родительский элемент ограничил объединенную цепь BIND между объединенной цепью IK и FK: но я продолжаю получать ошибку

"# Ошибка : TypeError: файл d: / Users / Имя / Documents / maya / 2020 / scripts \ DS_03C_autoHumanArm.py строка 217: можно только объединить список (не "str") в список # "

Мне нужен родитель ограничьте начальное соединение, конечное соединение, и, тем не менее, многие соединения находятся между их соответствующими дубликатами IK и FK, затем подключите outputX обратного узла к атрибуту w1 сгенерированного родительского ограничения и IK_Toggle сгенерированного переключателя IKFK к сгенерированному родительскому ограничению w0. Проблемы возникают вокруг строки 201:

С точки зрения того, что я пробовал до сих пор, в большинстве случаев, если метод двойного списка zip подробно описан здесь: Maya: Соединение двух цепочек соединений с помощью родительского ограничения но я не знаю, как адаптировать его для более чем двух соединенных цепей

'''
import DS_03C_autoHumanArm
reload (DS_03C_autoHumanArm)
DS_03C_autoHumanArm.gui()
'''

import maya.cmds as cmds
if cmds.window("moduleWin", exists =True):
    cmds.deleteUI("moduleWin", window = True)

myWindow = cmds.window("moduleWin",t='DS_joint_renamerV1',rtf=1,w=100, h=100, toolbox=True)
column = cmds.columnLayout(adj=True)

def gui():  
    #cmds.button(label='Print Instructions(Check Script Editor)',c=printInstructions)

    cmds.rowLayout(numberOfColumns = 3,adjustableColumn=2)
    cmds.textField('prefixText',it = 'lf',editable=True)
    cmds.textField('limbText',it='arm',editable=True)
    cmds.setParent('..')

    cmds.button( label="Rename Joint Chain",c=DS_module_rename)
    cmds.separator(h=9)

    cmds.columnLayout(adj=True)
    cmds.optionMenu('controlShape', label='Control Shape')
    cmds.menuItem( label='cog' )
    cmds.menuItem( label='cube' )
    cmds.menuItem( label='circle' )
    cmds.setParent('..')

    cmds.intSliderGrp('incDwnChain',
        label='Inc From End',
        min=0,
        max=10,
        value=1,
        field=True,
        columnWidth=[(1,80),(2,40),(3,150)])

    cmds.colorIndexSliderGrp('controlColor',
        label='Control Color',
        min=0,
        max=31,
        value=1,
        columnWidth=[(1,80),(2,40),(3,150)])

    cmds.button( label="Build Template",c=buildTemplate)
    cmds.separator(h=9)

    cmds.button( label="Finalise Limb",c=finaliseArm)
    cmds.separator(h=9)

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

def DS_module_rename(*args):
    namePref = cmds.textField('prefixText', query=True, text=True)
    limbPref = cmds.textField('limbText', query=True, text=True)
    ctlName = namePref+'_'+limbPref

    #list all joints in chain, this list will be refrenced by all the commands beneath it
    root = cmds.ls(sl=True)[0]
    child = cmds.listRelatives(root,ad=1,type='joint')
    limbJnt = child

    #rename the arm joints
    for j, name in enumerate(child):
        cmds.rename(name,ctlName + 'AJ{0}_BIND_JNT'.format(len(child)-j))
        print(child)

    root = cmds.ls(sl=True)[0]
    child = cmds.listRelatives(root,ad=1,f=True,children=True,type='joint')
    cmds.rename(child[0],ctlName +'AJ_BIND_END_JNT')
    cmds.rename(root,ctlName +'AJ_BIND_START_JNT')

def buildTemplate(*args):
    namePref = cmds.textField('prefixText', query=True, text=True)
    limbPref = cmds.textField('limbText', query=True, text=True)
    ctlName = namePref+'_'+limbPref

    shapePref = cmds.optionMenu('controlShape',query=True,value=True)
    incPref = cmds.intSliderGrp('incDwnChain',query=True,value=True)
    colorPref = cmds.colorIndexSliderGrp('controlColor',query=True,value=True) #this variable links to the color slider group in the GUI
    colorPref = colorPref -1 # this reverses the first variable to ensure you are getting the proper color from the color selector

    root = cmds.ls(sl=True)[0] # adding a zero bracket makes sure it counts the head of the herarchy too
    #root = cmds.ls(sl=True)[-1] # the brackets negative one gets the end of a list
    child = cmds.listRelatives(root,ad=1,type='joint')
    limbJnt = child

    ctl = ctlName+'_ikfk_toggle'

    if shapePref == 'cog':
        cmds.circle(n=ctl,nr = (90,0,0))
    elif shapePref == 'cube':
        cmds.circle(n=ctl,nr = (90,0,0))
    elif shapePref == 'circle':
        cmds.circle(n=ctl,nr = (90,0,0))

    cmds.addAttr(ctl,
        ln='IK_Toggle',
        defaultValue=1.0,
        minValue=0,
        maxValue=1,
        attributeType='float', 
        keyable=True)
    cmds.addAttr(ctl,
        ln='CONTROLS',
        at="enum",
        en="---------------:")
    cmds.setAttr(ctl + '.CONTROLS',
        k=True,
        lock=True)
    cmds.addAttr(ctl,
        ln='rotateAll',
        attributeType='float', 
        keyable=True)
    cmds.addAttr(ctl,
        ln='Spread',
        attributeType='float', 
        keyable=True)
    cmds.addAttr(ctl,
        ln='Scratch',
        attributeType='float', 
        keyable=True)

    cmds.group(n=ctlName+ 'AttrOrient_GRP')

    #forLoop/list increment to last of joint chain to place the IKFK toggle
    cmds.select(ctlName+'AJ1_BIND_JNT')

    #snap ikfk toggle to proper point on the joint chain without parent constraint
    baseCon = cmds.parentConstraint(child[incPref],ctlName+'AttrOrient_GRP',mo=False)

    #set color of control
    cmds.setAttr(ctl + '.overrideEnabled', 1)
    cmds.setAttr(ctl + '.overrideColor', colorPref)#create a textfield for manually enterring the number of the color

    cmds.createNode('reverse',n= ctlName + '_reverseNode')

    cmds.connectAttr(ctl + '.IK_Toggle', ctlName + '_reverseNode.inputX' )

    #list all FK joints in chain
    fkChain = cmds.duplicate(ctlName +'AJ_BIND_START_JNT', n= ctlName +'AJ_FK_START_JNT')
    fkList = cmds.listRelatives(ctlName +'AJ_FK_START_JNT', ad=True,pa=True)
    for fkn, name in enumerate(fkList):
        cmds.rename(name, ctlName +'AJ{0}_FK_JNT'.format(len(fkList)-fkn))

        #select FK chain, then,set joints size for easy grabbing on FK chain
        cmds.select(ctlName +'AJ_FK_START_JNT')

        fkRoot = cmds.ls(sl=True)[0] 
        fkChild = cmds.listRelatives(ctlName +'AJ_FK_START_JNT', ad=True,pa=True)
        fkChild.append(fkRoot)

        for r in fkChild:
            cmds.setAttr(r + '.radius', 2.0)

    ikChain = cmds.duplicate(ctlName +'AJ_BIND_START_JNT', n= ctlName +'AJ_IK_START_JNT')
    ikList = cmds.listRelatives(ctlName +'AJ_IK_START_JNT', ad=True,pa=True)
    for fkn, name in enumerate(ikList):
        cmds.rename(name, ctlName +'AJ{0}_FK_JNT'.format(len(ikList)-fkn))

        #select FK chain, then,set joints size for easy grabbing on FK chain
        cmds.select(ctlName +'AJ_IK_START_JNT')

        ikRoot = cmds.ls(sl=True)[0] 
        ikChild = cmds.listRelatives(ctlName +'AJ_IK_START_JNT', ad=True,pa=True)
        ikChild.append(ikRoot)

        for r in ikChild:
            cmds.setAttr(r + '.radius', 2.5)

def finaliseArm(*args):
    namePref = cmds.textField('prefixText', query=True, text=True)
    limbPref = cmds.textField('limbText', query=True, text=True)
    ctlName = namePref+'_'+limbPref
    ctl = namePref+limbPref+'_ikfk_toggle'

    ikJntChain=cmds.listRelatives(ctlName +'AJ_IK_START_JNT',ad=1,type='joint')
    ikJntChain.append(ctlName +'AJ_IK_START_JNT')
    ikJntChain.reverse()
    ikLimbJnt = ikJntChain

    print(ikJntChain)

    FKJntChain=cmds.listRelatives(ctlName +'AJ_FK_START_JNT',ad=1,type='joint')
    FKJntChain.append(ctlName +'AJ_IK_START_JNT')
    FKJntChain.reverse()
    FKLimbJnt = FKJntChain

    print(FKJntChain)

    boundJntChain=cmds.listRelatives(ctlName +'AJ_BIND_START_JNT',ad=1,type='joint')
    boundJntChain.append(ctlName +'AJ_BIND_START_JNT')
    boundJntChain.reverse()
    boundLimbJnt = boundJntChain

    print(boundJntChain)

    for ik_chain,fk_chain,bound_chain in zip(ikJntChain,FKJntChain,boundJntChain):
        spineCons = cmds.parentConstraint(ik_chain,fk_chain,bound_chain,mo=False)
        cmds.connectAttr(ctlName + '_reverseNode.outputX',spineCons+'.w1')
        cmds.connectAttr(ctl + '.IK_Toggle',spineCons+'.w0')

спасибо за вашу помощь

1 Ответ

0 голосов
/ 01 мая 2020

Ошибка, которую вы получаете, жалуется на то, что вы пытаетесь объединить список со строкой, чего Python не может сделать. В частности, spineCons - это список, и вместо этого вы можете просто получить доступ к его первому индексу, как этот spineCons[0].

Но есть и другие проблемы, как только вы это исправите. Во-первых, вы пытаетесь объединить '.w1' для подключения к атрибуту веса родительского ограничения, но это не правильное имя атрибута. Вы можете получить имена его атрибутов, вызвав cmds.parentConstraint(spineCons[0], q=True, weightAliasList=True).

Другая проблема заключается в том, что у вас есть 2 места, где вы забыли изменить IK на FK, в результате чего в шаблоне были построены 2 цепочки FK. !

И, наконец, последняя проблема в самом конце, когда вы пытаетесь подключиться ctl + '.IK_Toggle', потому что у этого объекта нет того атрибута, который существует. Я не слишком много копал в этом, но чтобы исправить это, вам просто нужно передать соответствующий объект.

Вот сценарий с исправлениями. Вы можете выполнить поиск на FIXME, чтобы увидеть, где я оставил комментарии:

'''
import DS_03C_autoHumanArm
reload (DS_03C_autoHumanArm)
DS_03C_autoHumanArm.gui()
'''

import maya.cmds as cmds
if cmds.window("moduleWin", exists =True):
    cmds.deleteUI("moduleWin", window = True)

myWindow = cmds.window("moduleWin",t='DS_joint_renamerV1',rtf=1,w=100, h=100, toolbox=True)
column = cmds.columnLayout(adj=True)

def gui():  
    #cmds.button(label='Print Instructions(Check Script Editor)',c=printInstructions)

    cmds.rowLayout(numberOfColumns = 3,adjustableColumn=2)
    cmds.textField('prefixText',it = 'lf',editable=True)
    cmds.textField('limbText',it='arm',editable=True)
    cmds.setParent('..')

    cmds.button( label="Rename Joint Chain",c=DS_module_rename)
    cmds.separator(h=9)

    cmds.columnLayout(adj=True)
    cmds.optionMenu('controlShape', label='Control Shape')
    cmds.menuItem( label='cog' )
    cmds.menuItem( label='cube' )
    cmds.menuItem( label='circle' )
    cmds.setParent('..')

    cmds.intSliderGrp('incDwnChain',
        label='Inc From End',
        min=0,
        max=10,
        value=1,
        field=True,
        columnWidth=[(1,80),(2,40),(3,150)])

    cmds.colorIndexSliderGrp('controlColor',
        label='Control Color',
        min=0,
        max=31,
        value=1,
        columnWidth=[(1,80),(2,40),(3,150)])

    cmds.button( label="Build Template",c=buildTemplate)
    cmds.separator(h=9)

    cmds.button( label="Finalise Limb",c=finaliseArm)
    cmds.separator(h=9)

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

def DS_module_rename(*args):
    namePref = cmds.textField('prefixText', query=True, text=True)
    limbPref = cmds.textField('limbText', query=True, text=True)
    ctlName = namePref+'_'+limbPref

    #list all joints in chain, this list will be refrenced by all the commands beneath it
    root = cmds.ls(sl=True)[0]
    child = cmds.listRelatives(root,ad=1,type='joint')
    limbJnt = child

    #rename the arm joints
    for j, name in enumerate(child):
        cmds.rename(name,ctlName + 'AJ{0}_BIND_JNT'.format(len(child)-j))
        print(child)

    root = cmds.ls(sl=True)[0]
    child = cmds.listRelatives(root,ad=1,f=True,children=True,type='joint')
    cmds.rename(child[0],ctlName +'AJ_BIND_END_JNT')
    cmds.rename(root,ctlName +'AJ_BIND_START_JNT')

def buildTemplate(*args):
    namePref = cmds.textField('prefixText', query=True, text=True)
    limbPref = cmds.textField('limbText', query=True, text=True)
    ctlName = namePref+'_'+limbPref

    shapePref = cmds.optionMenu('controlShape',query=True,value=True)
    incPref = cmds.intSliderGrp('incDwnChain',query=True,value=True)
    colorPref = cmds.colorIndexSliderGrp('controlColor',query=True,value=True) #this variable links to the color slider group in the GUI
    colorPref = colorPref -1 # this reverses the first variable to ensure you are getting the proper color from the color selector

    root = cmds.ls(sl=True)[0] # adding a zero bracket makes sure it counts the head of the herarchy too
    #root = cmds.ls(sl=True)[-1] # the brackets negative one gets the end of a list
    child = cmds.listRelatives(root,ad=1,type='joint')
    limbJnt = child

    ctl = ctlName+'_ikfk_toggle'

    if shapePref == 'cog':
        cmds.circle(n=ctl,nr = (90,0,0))
    elif shapePref == 'cube':
        cmds.circle(n=ctl,nr = (90,0,0))
    elif shapePref == 'circle':
        cmds.circle(n=ctl,nr = (90,0,0))

    cmds.addAttr(ctl,
        ln='IK_Toggle',
        defaultValue=1.0,
        minValue=0,
        maxValue=1,
        attributeType='float', 
        keyable=True)
    cmds.addAttr(ctl,
        ln='CONTROLS',
        at="enum",
        en="---------------:")
    cmds.setAttr(ctl + '.CONTROLS',
        k=True,
        lock=True)
    cmds.addAttr(ctl,
        ln='rotateAll',
        attributeType='float', 
        keyable=True)
    cmds.addAttr(ctl,
        ln='Spread',
        attributeType='float', 
        keyable=True)
    cmds.addAttr(ctl,
        ln='Scratch',
        attributeType='float', 
        keyable=True)

    cmds.group(n=ctlName+ 'AttrOrient_GRP')

    #forLoop/list increment to last of joint chain to place the IKFK toggle
    cmds.select(ctlName+'AJ1_BIND_JNT')

    #snap ikfk toggle to proper point on the joint chain without parent constraint
    baseCon = cmds.parentConstraint(child[incPref],ctlName+'AttrOrient_GRP',mo=False)

    #set color of control
    cmds.setAttr(ctl + '.overrideEnabled', 1)
    cmds.setAttr(ctl + '.overrideColor', colorPref)#create a textfield for manually enterring the number of the color

    cmds.createNode('reverse',n= ctlName + '_reverseNode')

    cmds.connectAttr(ctl + '.IK_Toggle', ctlName + '_reverseNode.inputX' )

    #list all FK joints in chain
    fkChain = cmds.duplicate(ctlName +'AJ_BIND_START_JNT', n= ctlName +'AJ_FK_START_JNT')
    fkList = cmds.listRelatives(ctlName +'AJ_FK_START_JNT', ad=True,pa=True)
    for fkn, name in enumerate(fkList):
        cmds.rename(name, ctlName +'AJ{0}_FK_JNT'.format(len(fkList)-fkn))

        #select FK chain, then,set joints size for easy grabbing on FK chain
        cmds.select(ctlName +'AJ_FK_START_JNT')

        fkRoot = cmds.ls(sl=True)[0] 
        fkChild = cmds.listRelatives(ctlName +'AJ_FK_START_JNT', ad=True,pa=True)
        fkChild.append(fkRoot)

        for r in fkChild:
            cmds.setAttr(r + '.radius', 2.0)

    ikChain = cmds.duplicate(ctlName +'AJ_BIND_START_JNT', n= ctlName +'AJ_IK_START_JNT')
    ikList = cmds.listRelatives(ctlName +'AJ_IK_START_JNT', ad=True,pa=True)
    for fkn, name in enumerate(ikList):
        cmds.rename(name, ctlName +'AJ{0}_IK_JNT'.format(len(ikList)-fkn))  # FIXME: This should be ik!

        #select FK chain, then,set joints size for easy grabbing on FK chain
        cmds.select(ctlName +'AJ_IK_START_JNT')

        ikRoot = cmds.ls(sl=True)[0] 
        ikChild = cmds.listRelatives(ctlName +'AJ_IK_START_JNT', ad=True,pa=True)
        ikChild.append(ikRoot)

        for r in ikChild:
            cmds.setAttr(r + '.radius', 2.5)

def finaliseArm(*args):
    namePref = cmds.textField('prefixText', query=True, text=True)
    limbPref = cmds.textField('limbText', query=True, text=True)
    ctlName = namePref+'_'+limbPref
    ctl = namePref+limbPref+'_ikfk_toggle'

    ikJntChain=cmds.listRelatives(ctlName +'AJ_IK_START_JNT',ad=1,type='joint')
    ikJntChain.append(ctlName +'AJ_IK_START_JNT')
    ikJntChain.reverse()
    ikLimbJnt = ikJntChain

    print(ikJntChain)

    FKJntChain=cmds.listRelatives(ctlName +'AJ_FK_START_JNT',ad=1,type='joint')
    FKJntChain.append(ctlName +'AJ_FK_START_JNT')  # FIXME: This was using IK before!
    FKJntChain.reverse()
    FKLimbJnt = FKJntChain

    print(FKJntChain)

    boundJntChain=cmds.listRelatives(ctlName +'AJ_BIND_START_JNT',ad=1,type='joint')
    boundJntChain.append(ctlName +'AJ_BIND_START_JNT')
    boundJntChain.reverse()
    boundLimbJnt = boundJntChain

    print(boundJntChain)

    for ik_chain,fk_chain,bound_chain in zip(ikJntChain,FKJntChain,boundJntChain):
        spineCons = cmds.parentConstraint(ik_chain,fk_chain,bound_chain,mo=False)
        weightAttrs = cmds.parentConstraint(spineCons[0], q=True, weightAliasList=True)  # FIXME: Get constraint weight attribute names.
        cmds.connectAttr(ctlName + '_reverseNode.outputX',spineCons[0] + '.' + weightAttrs[1])  # FIXME: `spineCons` is a list, so make sure to access its first index.
        cmds.connectAttr(ctl + '.IK_Toggle',spineCons[0] + '.' + weightAttrs[0])  # FIXME: This will error because `IK_Toggle` doesn't exist
...