//****************************************************************************** // // 版权所有: 玉溪时光科技有限公司 // 联系邮箱: q.100@qq.com // 开发日期: 2023/08/08 // //****************************************************************************** global proc SGEnableJointOrient(){} global proc SGCometJointOrient() { if (!`window -ex SuperRiggingEditor`){ return; } global string $SG_version ; global string $SG_date ; string $ShowAxis = "Show Axis"; string $HideAxis = "Hide Axis"; string $AimAxis = "Aim Axis:"; string $UpAxis = "Up Axis:"; string $Reverse = "Reverse"; string $WorldUpDir = "World Up Dir:"; string $AutoGuessUpDirection = "Auto-Guess Up Direction"; string $OrientJoints = "Orient Joints"; string $Tweak = "Tweak:"; string $Zero = "Zero"; string $ManualAddRotTweak = "Manual + Rot Tweak"; string $ManualRedRotTweak = "Manual - Rot Tweak"; string $MainJointAmendAxis = "Main Joint Amend Axis"; string $SkinJointAmendAxis = "Skin Joint Amend Axis"; if(`SGDescriptor -l` == "ZH"){ $ShowAxis = "显示坐标轴"; $HideAxis = "隐藏坐标轴"; $AimAxis = "目标轴:"; $UpAxis = "向上轴:"; $Reverse = "反向"; $WorldUpDir = "世界向上方向:"; $AutoGuessUpDirection = "自动识别上方向"; $OrientJoints = "确定关节方向"; $Tweak = "调整:"; $Zero = "清零"; $ManualAddRotTweak = "手动旋转调整+"; $ManualRedRotTweak = "手动旋转调整-"; $MainJointAmendAxis = "主要关节修正轴"; $SkinJointAmendAxis = "蒙皮关节修正轴"; } if (`window -ex cometJointOrientWin`) { deleteUI -window cometJointOrientWin; } window -p SuperRiggingEditor -w 310 -h 256 -t "JointOrient" -s true -tb true cometJointOrientWin; formLayout mainForm ; separator -style "in" -h 3 sep0 ; button -l $ShowAxis -al "center" -c ("ShowAxis 1;") -ann ("Show Local Axis") btnShow ; button -l $HideAxis -al "center" -c ("ShowAxis 0;") -ann ("Hide Local Axis") btnHide ; radioButtonGrp -l $AimAxis -nrb 3 -la3 "X" "Y" "Z" -sl 2 -cw4 80 40 40 40 rbgAim ; radioButtonGrp -l $UpAxis -nrb 3 -la3 "X" "Y" "Z" -sl 1 -cw4 80 40 40 40 rbgUp ; checkBox -l $Reverse -v 0 cbRevAim ; checkBox -l $Reverse -v 0 cbRevUp ; separator -style "in" -h 6 sep1 ; floatFieldGrp -nf 3 -label $WorldUpDir -v1 1.0 -v2 0.0 -v3 0.0 -cw4 80 50 50 50 ffgUpDir ; button -l "X" -w 20 -c ("floatFieldGrp -e -v1 1.0 -v2 0.0 -v3 0.0 ffgUpDir; ") -ann ("Auto Set UpDir to X-Axis") btnX ; button -l "Y" -w 20 -c ("floatFieldGrp -e -v1 0.0 -v2 1.0 -v3 0.0 ffgUpDir; ") -ann ("Auto Set UpDir to Y-Axis") btnY ; button -l "Z" -w 20 -c ("floatFieldGrp -e -v1 0.0 -v2 0.0 -v3 1.0 ffgUpDir; ") -ann ("Auto Set UpDir to Z-Axis") btnZ ; checkBox -l $AutoGuessUpDirection -v 0 cbAutoDir ; button -l $OrientJoints -al "center" -c ("SGOrientUI();") -ann ("Orient selected joints based on settings above.") btnOJ; separator -style "in" -h 6 sepBig ; floatFieldGrp -nf 3 -label $Tweak -v1 0.0 -v2 0.0 -v3 0.0 -cw4 80 50 50 50 ffgTweak ; button -l $Zero -w 58 -c ("floatFieldGrp -e -v1 0.0 -v2 0.0 -v3 0.0 ffgTweak; ") -ann ("Zero's tweak values.") btnZero ; popupMenu -p ffgTweak ; menuItem -l "X=1" -c ("floatFieldGrp -e -v1 1.0 ffgTweak ; ") ; menuItem -l "Y=1" -c ("floatFieldGrp -e -v2 1.0 ffgTweak ; ") ; menuItem -l "Z=1" -c ("floatFieldGrp -e -v3 1.0 ffgTweak ; ") ; menuItem -divider true ; menuItem -l "X=5" -c ("floatFieldGrp -e -v1 5.0 ffgTweak ; ") ; menuItem -l "Y=5" -c ("floatFieldGrp -e -v2 5.0 ffgTweak ; ") ; menuItem -l "Z=5" -c ("floatFieldGrp -e -v3 5.0 ffgTweak ; ") ; menuItem -divider true ; menuItem -l "X=10" -c ("floatFieldGrp -e -v1 10.0 ffgTweak ; ") ; menuItem -l "Y=10" -c ("floatFieldGrp -e -v2 10.0 ffgTweak ; ") ; menuItem -l "Z=10" -c ("floatFieldGrp -e -v3 10.0 ffgTweak ; ") ; button -l $ManualAddRotTweak -al "center" -c ("SGTweakUI(1.0);") -ann ("Manually rotates selected joints axis positive.") btnTweakP ; button -l $ManualRedRotTweak -al "center" -c ("SGTweakUI(-1.0);") -ann ("Manually rotates selected joints axis negative.") btnTweakN ; separator -style "in" -h 6 sep2 ; button -l $MainJointAmendAxis -al "center" -c ("SGMainAmendAxis;") -ann ("Main Amend Axis") btnMainAmend ; button -l $SkinJointAmendAxis -al "center" -c ("SGSkinAmendAxis;") -ann ("Other Amend Axis") btnOtherAmend ; separator -style "in" -h 6 sep3 ; formLayout -e -af sep0 "left" 0 -af sep0 "right" 0 -af sep0 "top" 0 -an sep0 "bottom" -af btnShow "left" 5 -ap btnShow "right" 0 49 -ac btnShow "top" 3 sep0 -an btnShow "bottom" -ap btnHide "left" 0 51 -af btnHide "right" 5 -ac btnHide "top" 3 sep0 -an btnHide "bottom" -af rbgAim "left" 0 -an rbgAim "right" -ac rbgAim "top" 0 btnShow -an rbgAim "bottom" -ac cbRevAim "left" 0 rbgAim -af cbRevAim "right" 0 -ac cbRevAim "top" 0 btnShow -an cbRevAim "bottom" -af rbgUp "left" 0 -an rbgUp "right" -ac rbgUp "top" 0 rbgAim -an rbgUp "bottom" -ac cbRevUp "left" 0 rbgUp -af cbRevUp "right" 0 -ac cbRevUp "top" 0 rbgAim -an cbRevUp "bottom" -af sep1 "left" 0 -af sep1 "right" 0 -ac sep1 "top" 0 rbgUp -an sep1 "bottom" -af ffgUpDir "left" 0 -an ffgUpDir "right" -ac ffgUpDir "top" 0 sep1 -an ffgUpDir "bottom" -ac btnX "left" 2 ffgUpDir -an btnX "right" -ac btnX "top" 0 sep1 -an btnX "bottom" -ac btnY "left" 2 btnX -an btnY "right" -ac btnY "top" 0 sep1 -an btnY "bottom" -ac btnZ "left" 2 btnY -an btnZ "right" -ac btnZ "top" 0 sep1 -an btnZ "bottom" -af cbAutoDir "left" 20 -af cbAutoDir "right" 0 -ac cbAutoDir "top" 0 ffgUpDir -an cbAutoDir "bottom" -af btnOJ "left" 5 -af btnOJ "right" 5 -ac btnOJ "top" 5 cbAutoDir -an btnOJ "bottom" -af sepBig "left" 0 -af sepBig "right" 0 -ac sepBig "top" 5 btnOJ -an sepBig "bottom" -af ffgTweak "left" 0 -an ffgTweak "right" -ac ffgTweak "top" 5 sepBig -an ffgTweak "bottom" -ac btnZero "left" 2 ffgTweak -an btnZero "right" -ac btnZero "top" 5 sepBig -an btnZero "bottom" -af btnTweakP "left" 5 -ap btnTweakP "right" 0 49 -ac btnTweakP "top" 5 ffgTweak -an btnTweakP "bottom" -ap btnTweakN "left" 0 51 -af btnTweakN "right" 5 -ac btnTweakN "top" 5 ffgTweak -an btnTweakN "bottom" -af sep2 "left" 0 -af sep2 "right" 0 -ac sep2 "top" 2 btnTweakP -an sep2 "bottom" -af btnMainAmend "left" 5 -af btnMainAmend "right" 5 -ac btnMainAmend "top" 3 sep2 -an btnMainAmend "bottom" -af btnOtherAmend "left" 5 -af btnOtherAmend "right" 5 -ac btnOtherAmend "top" 1 btnMainAmend -an btnOtherAmend "bottom" -af sep3 "left" 0 -af sep3 "right" 0 -ac sep3 "top" 0 btnOtherAmend -an sep3 "bottom" mainForm ; showWindow cometJointOrientWin; } // -------------------------------------------------------------------------- /* * SGOrientUI() - UI wrapper for starting an orient */ global proc SGOrientUI() { print ("// cometJointOrient\n"); int $nAimAxis = `radioButtonGrp -q -sl rbgAim` ; int $nUpAxis = `radioButtonGrp -q -sl rbgUp` ; float $aimAxis[] = {0,0,0} ; float $upAxis[] = {0,0,0} ; float $revAim = 1.0 ; if (`checkBox -q -v cbRevAim`) $revAim = -1.0 ; float $revUp = 1.0 ; if (`checkBox -q -v cbRevUp`) $revUp = -1.0 ; if ($nAimAxis == $nUpAxis) warning -sl 0 ("The AIM and UP axis are the same! Orientaiton probably won't work!") ; $aimAxis[ ($nAimAxis-1) ] = $revAim ; $upAxis[ ($nUpAxis-1) ] = $revUp ; float $upDir[3] ; $upDir[0] = `floatFieldGrp -q -v1 ffgUpDir` ; $upDir[1] = `floatFieldGrp -q -v2 ffgUpDir` ; $upDir[2] = `floatFieldGrp -q -v3 ffgUpDir` ; int $doAuto = `checkBox -q -v cbAutoDir` ; string $joints[] = `ls -type "joint" -sl` ; // Now do it! SGOrient($joints, $aimAxis, $upAxis, $upDir, $doAuto) ; // End with same stuff selected! select -r $joints ; } // -------------------------------------------------------------------------- /* * SGOrient() - The real worker orient proc. * * $joints is array of joints to orient * $aimAxis = is xyz array of what axis of joint does aim * $upAxis = is xyz array of what axis of joint does up * $upDir = what vector to use for up direction? * $doAuto = If possible will try to guess the up axis otherwise * it will use prev joint up axis or else world upDir. * */ global proc SGOrient(string $joints[], float $aimAxis[], float $upAxis[], float $upDir[], int $doAuto) { int $nJnt = size($joints) ; int $i; vector $prevUp = <<0,0,0>>; // Now orient each joint for ($i=0; $i < $nJnt; ++$i) { // First we need to unparent everything and then store that, string $childs[] = `listRelatives -children -type "transform" -type "joint" $joints[$i]` ; if (size($childs) > 0) $childs = `parent -w $childs` ; // unparent and get NEW names in case they changed... // Find parent for later in case we need it. string $parents[] = `listRelatives -parent $joints[$i]` ; string $parent = $parents[0] ; // Now if we have a child joint...aim to that. string $aimTgt="" ; string $child ; for ($child in $childs) { if (nodeType($child) == "joint") { $aimTgt = $child ; break ; } } // print ("// DEBUG: JNT="+$joints[$i]+" Parent="+$parent+" AimTgt="+$aimTgt+" //\n") ; if ($aimTgt != "") { float $upVec[3] = {0,0,0} ; // First off...if $doAuto is on, we need to guess the cross axis dir. // if ($doAuto) { // Now since the first joint we want to match the second orientation // we kind of hack the things passed in if it is the first joint // ie: If the joint doesn't have a parent...OR if the parent it has // has the "same" position as itself...then we use the "next" joints // as the up cross calculations // float $posJ[3] = `xform -q -ws -rp $joints[$i]` ; float $posP[3] = $posJ ; if ($parent != "") $posP = `xform -q -ws -rp $parent` ; float $tol = 0.0001 ; // How close to we consider "same"? if ($parent == "" || (abs($posJ[0] - $posP[0]) <= $tol && abs($posJ[1] - $posP[1]) <= $tol && abs($posJ[2] - $posP[2]) <= $tol )) { string $aimChilds[] = `listRelatives -children $aimTgt` ; string $aimChild = "" ; string $child ; for ($child in $aimChilds) { if (nodeType($child) == "joint") { $aimChild = $child ; break ; } } $upVec = SGGetCrossDir($joints[$i], $aimTgt, $aimChild) ; } else $upVec = SGGetCrossDir($parent, $joints[$i], $aimTgt) ; } if (!$doAuto || ($upVec[0] == 0.0 && $upVec[1] == 0.0 && $upVec[2] == 0.0)) $upVec = $upDir ; // or else use user set up Dir. if needed string $aCons[] = `aimConstraint -aim $aimAxis[0] $aimAxis[1] $aimAxis[2] -upVector $upAxis[0] $upAxis[1] $upAxis[2] -worldUpVector $upVec[0] $upVec[1] $upVec[2] -worldUpType "vector" -weight 1.0 $aimTgt $joints[$i]` ; delete $aCons ; // Now compare the up we used to the prev one. vector $curUp = << $upVec[0], $upVec[1], $upVec[2] >> ; $curUp = unit($curUp) ; float $dot = $curUp * $prevUp ; // dot product for angle betwen... $prevUp = << $upVec[0], $upVec[1], $upVec[2] >> ; // store for later if ($i > 0 && $dot <= 0.0) { // Adjust the rotation axis 180 if it looks like we've flopped the wrong way! xform -r -os -ra ($aimAxis[0]*180.0) ($aimAxis[1]*180.0) ($aimAxis[2]*180.0) $joints[$i] ; $prevUp *= -1.0 ; } // And now finish clearing out joint axis... joint -e -zso $joints[$i] ; makeIdentity -apply true $joints[$i] ; } else if ($parent != "") { // Otherwise if there is no target, just dup orienation of parent... string $oCons[] = `orientConstraint -weight 1.0 $parent $joints[$i]` ; delete $oCons ; // And now finish clearing out joint axis... joint -e -zso $joints[$i] ; makeIdentity -apply true $joints[$i] ; } // Now that we're done... reparent if (size($childs) > 0) parent $childs $joints[$i] ; } } // -------------------------------------------------------------------------- /* * SGGetCrossDir() - Given three nodes, this gets the cross product of * the directions from B->A and B->C. */ global proc float[] SGGetCrossDir(string $objA, string $objB, string $objC) { float $cross[3] = {0,0,0} ; if ($objA == "" || $objB == "" || $objC == "" || objExists($objA) != true || objExists($objB) != true || objExists($objC) != true) return $cross ; float $posA[3] = `xform -q -ws -rp $objA` ; float $posB[3] = `xform -q -ws -rp $objB` ; float $posC[3] = `xform -q -ws -rp $objC` ; vector $v1 = << $posA[0]-$posB[0], $posA[1]-$posB[1], $posA[2]-$posB[2] >> ; vector $v2 = << $posC[0]-$posB[0], $posC[1]-$posB[1], $posC[2]-$posB[2] >> ; vector $vC = $v1 ^ $v2 ; // Do cross product! $vC = unit($vC) ; // normalize $cross[0] = $vC.x ; $cross[1] = $vC.y ; $cross[2] = $vC.z ; return $cross ; } // -------------------------------------------------------------------------- /* * SGTweakUI() - UI wrapper for starting a joint tweak */ global proc SGTweakUI(float $mult) { float $rot[3] ; $rot[0] = `floatFieldGrp -q -v1 ffgTweak` * $mult ; $rot[1] = `floatFieldGrp -q -v2 ffgTweak` * $mult ; $rot[2] = `floatFieldGrp -q -v3 ffgTweak` * $mult ; string $joints[] = `ls -type "joint" -sl` ; string $jonitTmp[]; for($j=0; $j 0.001 || $pos[0] < -0.001 || $pos[1] > 0.001 || $pos[1] < -0.001 || $pos[2] > 0.001 || $pos[2] < -0.001) { setAttr -type float3 ($orientConstraint_drv + ".offset") ($pos[0]*-1) $pos[1] $pos[2]; } } string $orientConstraint_body = `checkOrientConstraintConnection $joint_body`; if(`objExists $orientConstraint_body`){ float $pos[] = `getAttr ($joint_body + ".rotate")`; if($pos[0] > 0.001 || $pos[0] < -0.001 || $pos[1] > 0.001 || $pos[1] < -0.001 || $pos[2] > 0.001 || $pos[2] < -0.001) { setAttr -type float3 ($orientConstraint_body + ".offset") ($pos[0]*-1) $pos[1] $pos[2]; } } } else if($type[0] == "muscle"){ if(`objExists $joint_body`){ setAttr -type float3 ($joint_body + ".jointOrient") 0 0 0; float $pos[] = `getAttr ($joint_body + ".rotate")`; setAttr -type float3 ($joint_body + ".jointOrient") $pos[0] $pos[1] $pos[2]; } if(`objExists $joint_head`){ setAttr -type float3 ($joint_head + ".jointOrient") 0 0 0; float $pos[] = `getAttr ($joint_head + ".rotate")`; setAttr -type float3 ($joint_head + ".jointOrient") $pos[0] $pos[1] $pos[2]; } } if(`objExists $joint_drv`){ float $drvRot[] = `getAttr ($joint_drv+".jo")`; if(`objExists $joint_head` && $type[0] != "half" && $type[0] != "muscle") { setAttr -type "float3" ($joint_head+".jo") $drvRot[0] $drvRot[1] $drvRot[2]; } if(`objExists $joint_body` && $type[0] != "half" && $type[0] != "muscle") { setAttr -type "float3" ($joint_body+".jo") $drvRot[0] $drvRot[1] $drvRot[2]; } } } SGProgressBar -ep; } global proc SGOtherAmendAxis(int $nJoint[]){ string $joints[] = `SGBodyJoints`; string $joint[]; for($j=0; $j