# http://tech-coyote.com/archives/1077
# スカートリグ サンプル
# -*- coding: utf-8 -*-
import maya.cmds as cmds
import maya.mel as mel
import maya.OpenMaya as om
# ① set作成
def createJTSet_exe():
srcJT = 'SourceJoint'
srcJT_end = 'SourceJoint_End'
wgtLct_src = 'WeightLoc_Source'
wgtLct = 'WeightLoc'
gp = 'skirtJT_weightCalcurateSrc_Gp'
cmds.joint(p = [0, 0, 0], n = srcJT) # 'SourceJoint'
cmds.joint(p = [6, 0, 0], n = srcJT_end) # 'SourceJoint_End'
cmds.spaceLocator(p = [0, 0, 0], n = wgtLct_src)
cmds.parent(wgtLct_src, srcJT)
cmds.spaceLocator(p = [0, 0, 0], n = wgtLct)
cmds.group(srcJT, wgtLct, n = gp)
cmds.delete(cmds.pointConstraint(srcJT_end, wgtLct_src, offset =[0, 0, 0], weight = 1)) # 'WeightLoc_Source'
om.MGlobal.displayInfo(u'done')
createJTSet_exe()
# ② 足のジョイントの回転値を受け取るジョイントや必要なロケーターを作成
ifJT = 'hip_if_L'
def decompMat_exe():
srcJT = 'SourceJoint'
wgtLct_src = 'WeightLoc_Source'
wgtLct = 'WeightLoc'
decompMat = cmds.createNode('decomposeMatrix')
cmds.connectAttr("%s.worldMatrix[0]" % wgtLct_src, "%s.inputMatrix" % decompMat, f = True)
cmds.connectAttr("%s.outputTranslateY" % decompMat, "%s.translateY" % wgtLct, f = True)
cmds.connectAttr("%s.outputTranslateZ" % decompMat, "%s.translateZ" % wgtLct, f = True)
om.MGlobal.displayInfo(u'done')
decompMat_exe()
def elrAndQat_exe(ifJT):
srcJT = 'SourceJoint'
elr2Qat = cmds.createNode('eulerToQuat')
qat2Elr = cmds.createNode('quatToEuler')
# connectAttr -f WeightLoc_Source.worldMatrix[0] decomposeMatrix1.inputMatrix;
# connectAttr -f decomposeMatrix1.outputTranslateY WeightLoc.translateY;
# connectAttr -f decomposeMatrix1.outputTranslateZ WeightLoc.translateZ;
cmds.connectAttr("%s.rotate" % ifJT, "%s.inputRotate" % elr2Qat, f = True)
cmds.connectAttr("%s.outputQuat" % elr2Qat, "%s.inputQuat" % qat2Elr, f = True)
cmds.connectAttr("%s.outputRotate" % qat2Elr, "%s.rotate" % srcJT, f = True)
# connectAttr -f hip_jt_L.rotate eulerToQuat1.inputRotate;
# connectAttr -f eulerToQuat1.outputQuat quatToEuler1.inputQuat;
# connectAttr -f quatToEuler1.outputRotate SourceJoint.rotate;
om.MGlobal.displayInfo(u'done')
elrAndQat_exe(ifJT)
# ③ 最終的に回転値をジョイントに受け渡すためのトランスフォーム等を作成
# -*- coding: utf-8 -*-
import maya.cmds as cmds
# selection 共通関数 v3 -flatten込み-
def commonCheckSelection(*args):
u""" <selection 共通関数 v3 -flatten込み>
:return selList:
:rtype selList: list of unicode
"""
selList = cmds.ls(sl = True, flatten = True) or []
# print(selList)
# if not len(selList):
# print('\n' + '***' * 10)
# print(u'# result : node を選択し、してください。')
# print('***' * 20 + '\n')
# else:
# print('\n' + '***' * 10)
# print(u'# result : commonCheckSelection:継続中')
# print('***' * 10 + '\n')
print(selList)
# print(type(selList))
# for index in selList:
# print(index)
# print(type(index)) # type 'unicode'
return selList
skirtJT = commonCheckSelection()
if len(skirtJT):
skirtJT = skirtJT[0]
print(skirtJT)
def skirtrJT_exe(skirtJT):
cmds.select(skirtJT, r = True)
import YO_createSpaceNode
# 1. skirt_jtAConnect_AL < -- skirtJT と同じ向き
YO_createSpaceNode.exe(typ = 1, nt = 'locator', n = [u'~', u'~[Space]', u'~', u'', u''])
newNode = cmds.ls(sl = True, r = True) or []
newNode = newNode[0]
newName = newNode.replace('Space', 'Connect')
cmds.rename(newNode, newName)
newNode = cmds.ls(sl = True, r = True) or []
skirt_jt_connect = newNode[0]
cmds.ungroup()
mel.eval("swap")
# 2. skirt_jtATransNode_AL < -- ifJT と同じ向き
cmds.select(skirtJT, r = True)
YO_createSpaceNode.exe(typ = 1, nt = 'locator', n = [u'~', u'~[Space]', u'~', u'', u''])
newNode = cmds.ls(sl = True, r = True) or []
newNode = newNode[0]
newName = newNode.replace('Space', 'TransNode')
cmds.rename(newNode, newName)
newNode = cmds.ls(sl = True, r = True) or []
skirt_jt_transNode = newNode[0]
cmds.ungroup()
mel.eval("swap")
oriConst = cmds.orientConstraint(ifJT, skirt_jt_transNode)[0]
cmds.delete(oriConst)
# 3. skirt_jtATransOffset_AL < -- ifJT と同じ向き。つまり、2. のspace
cmds.select(skirt_jt_transNode, r = True)
YO_createSpaceNode.exe(typ = 1, nt = 'locator', n = [u'~', u'~[Space]', u'~', u'', u''])
newNode = cmds.ls(sl = True, r = True) or []
newNode = newNode[0]
newName = newNode.replace('TransNodeSpace', 'TransOffset')
cmds.rename(newNode, newName)
newNode = cmds.ls(sl = True, r = True) or []
skirt_jt_transOffset = newNode[0]
# 階層の整理
cmds.parent(skirt_jt_connect, skirt_jt_transNode)
return skirt_jt_transOffset, skirt_jt_transNode, skirt_jt_connect
om.MGlobal.displayInfo(u'done')
skirt_jt_transOffset, skirt_jt_transNode, skirt_jt_connect = skirtrJT_exe(skirtJT)
print(skirt_jt_transOffset, skirt_jt_transNode, skirt_jt_connect)
# ④ ロケーターの移動値をpairBlendノードのウェイトに使用するために、ノードを構築
clmp = cmds.createNode('clamp')
cmds.setAttr('%s.minR' % clmp, -1)
cmds.setAttr('%s.maxR' % clmp, 0)
cmds.setAttr('%s.minG' % clmp, 0)
cmds.setAttr('%s.maxG' % clmp, 1)
cmds.setAttr('%s.minB' % clmp, 0)
cmds.setAttr('%s.maxB' % clmp, 1)
cmds.connectAttr("%s.ty" % wgtLct, "%s.inputR" % clmp, f = True)
cmds.connectAttr("%s.ty" % wgtLct, "%s.inputG" % clmp, f = True)
cmds.connectAttr("%s.tz" % wgtLct, "%s.inputB" % clmp, f = True)
multD = cmds.createNode('multiplyDivide')
cmds.setAttr('%s.input2X' % multD, -1)
cmds.connectAttr("%s.output" % clmp, "%s.input1" % multD, f = True)
'''
setAttr "clamp1.minR" -1;
setAttr "clamp1.maxR" 0;
setAttr "clamp1.minG" 0;
setAttr "clamp1.maxG" 1;
setAttr "clamp1.minB" 0;
setAttr "clamp1.maxB" 1;
connectAttr -f WeightLoc.translateY clamp1.inputR;
connectAttr -f WeightLoc.translateY clamp1.inputG;
connectAttr -f WeightLoc.translateZ clamp1.inputB;
setAttr "multiplyDivide1.input2X" -1;
connectAttr -f clamp1.output multiplyDivide1.input1;
'''
# 視認性を加味
cmds.addAttr('clamp1', ln="outX", dv=0, at='double')
cmds.setAttr('clamp1.outX', e=1, keyable=True)
cmds.addAttr('clamp1', ln="outY", dv=0, at='double')
cmds.setAttr('clamp1.outY', e=1, keyable=True)
cmds.addAttr('clamp1', ln="outZ", dv=0, at='double')
cmds.setAttr('clamp1.outZ', e=1, keyable=True)
cmds.connectAttr('clamp1.outputR', 'clamp1.outX', f=1)
cmds.connectAttr('clamp1.outputG', 'clamp1.outY', f=1)
cmds.connectAttr('clamp1.outputB', 'clamp1.outZ', f=1)
# 視認性を加味
cmds.addAttr('multiplyDivide1', ln="outX", dv=0, at='double')
cmds.setAttr('multiplyDivide1.outX', e=1, keyable=True)
cmds.addAttr('multiplyDivide1', ln="outY", dv=0, at='double')
cmds.setAttr('multiplyDivide1.outY', e=1, keyable=True)
cmds.addAttr('multiplyDivide1', ln="outZ", dv=0, at='double')
cmds.setAttr('multiplyDivide1.outZ', e=1, keyable=True)
cmds.connectAttr('multiplyDivide1.outputX', 'multiplyDivide1.outX', f=1)
cmds.connectAttr('multiplyDivide1.outputY', 'multiplyDivide1.outY', f=1)
cmds.connectAttr('multiplyDivide1.outputZ', 'multiplyDivide1.outZ', f=1)
# ⑤ 前後と横用のpairBlendノードを作成
# 1.
frontPB = 'front_pairBlend'
backPB = 'back_pairBlend'
sidePB = 'side_pairBlend'
frontSidePB = 'frontSide_pairBlend'
backSidePB = 'backSide_pairBlend'
if not cmds.objExists(frontPB):
frontPB = cmds.createNode('pairBlend', n = 'front_pairBlend')
if not cmds.objExists(backPB):
backPB = cmds.createNode('pairBlend', n = 'back_pairBlend')
if not cmds.objExists(sidePB):
sidePB = cmds.createNode('pairBlend', n = 'side_pairBlend')
if not cmds.objExists(frontSidePB):
frontSidePB = cmds.createNode('pairBlend', n = 'frontSide_pairBlend')
if not cmds.objExists(backSidePB):
backSidePB = cmds.createNode('pairBlend', n = 'backSide_pairBlend')
# frontPB
cmds.connectAttr("%s.outputX" % multD, "%s.weight" % frontPB, f = True)
cmds.connectAttr("%s.rotate" % srcJT, "%s.inRotate2" % frontPB, f = True)
# backPB
cmds.connectAttr("%s.outputY" % multD, "%s.weight" % backPB, f = True)
cmds.connectAttr("%s.rotate" % srcJT, "%s.inRotate2" % backPB, f = True)
# sidePB
cmds.connectAttr("%s.outputZ" % multD, "%s.weight" % sidePB, f = True)
cmds.connectAttr("%s.rotate" % srcJT, "%s.inRotate2" % sidePB, f = True)
# frontSidePB
cmds.connectAttr('%s.outRotate' % frontPB, '%s.inRotate2' % frontSidePB, f=1)
cmds.connectAttr('%s.outRotate' % sidePB, '%s.inRotate1' % frontSidePB, f=1)
cmds.connectAttr('%s.outputX' % multD, '%s.weight' % frontSidePB, f=1)
# backSidePB
cmds.connectAttr('%s.outRotate' % backPB, '%s.inRotate2' % backSidePB, f=1)
cmds.connectAttr('%s.outRotate' % sidePB, '%s.inRotate1' % backSidePB, f=1)
cmds.connectAttr('%s.outputY' % multD, '%s.weight' % backSidePB, f=1)
'''
connectAttr -f multiplyDivide1.outputX front_pairBlend.weight;
connectAttr -f SourceJoint.rotate front_pairBlend.inRotate2;
connectAttr -f multiplyDivide1.outputY back_pairBlend.weight;
connectAttr -f SourceJoint.rotate back_pairBlend.inRotate2;
connectAttr -f multiplyDivide1.outputZ side_pairBlend.weight;
connectAttr -f SourceJoint.rotate side_pairBlend.inRotate2;
'''
'''
connectAttr -f front_pairBlend.outRotate frontSide_pairBlend.inRotate2;
connectAttr -f side_pairBlend.outRotate frontSide_pairBlend.inRotate1;
connectAttr -f multiplyDivide1.outputX frontSide_pairBlend.weight;
'''
'''
connectAttr -f back_pairBlend.outRotate backSide_pairBlend.inRotate2;
connectAttr -f side_pairBlend.outRotate backSide_pairBlend.inRotate1;
connectAttr -f multiplyDivide1.outputY backSide_pairBlend.weight;
'''
# 2. 手動でコネクションする。。
# ex:
# cmds.connectAttr('%s.outRotate' % frontPB, '%s.rotate' % skirt_jt_transNode, f=True)
# '''
#connectAttr -f front_pairBlend.outRotate skirt_jtATransNode_AL.rotate;
# '''
# cmds.orientConstraint(skirt_jt_connect, skirtJT)
# 3. 調整!!
# 3.1 いじってみる!! v1
#cmds.setAttr("WeightLoc_Source.translateX", 1)
#cmds.setAttr("WeightLoc.translateX", 1)
#cmds.setAttr("clamp1.minR", 0)
#cmds.setAttr("clamp1.maxR", 1)
#cmds.setAttr("clamp1.minG", -1)
#cmds.setAttr("clamp1.maxG", 0)
#cmds.setAttr("clamp1.minB", 0)
#cmds.setAttr("clamp1.maxB", 1)
#cmds.setAttr("multiplyDivide1.input2X", 1)
#cmds.setAttr("multiplyDivide1.input2Y", -1)
#cmds.setAttr("multiplyDivide1.input2Z", 1)
# 3.2 いじってみる!! v2
cmds.setAttr("WeightLoc_Source.translateX", 1)
cmds.setAttr("WeightLoc.translateX", 1)
cmds.setAttr("clamp1.minR", 0)
cmds.setAttr("clamp1.maxR", 1)
cmds.setAttr("clamp1.minG", -1)
cmds.setAttr("clamp1.maxG", 0)
cmds.setAttr("clamp1.minB", -1)
cmds.setAttr("clamp1.maxB", 0
cmds.setAttr("multiplyDivide1.input2X", 1)
cmds.setAttr("multiplyDivide1.input2Y", -1)
cmds.setAttr("multiplyDivide1.input2Z", -1)