--run this script with your skinned mesh selected. --this is a combination of my own functions for finding the bone we want to lose and what its closest remaining parent would be (get put into a fromToBones array) --and also making use of some of Stews functions from autolod. ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- bonesToKeep = #( --array of all bones we want to keep "SKEL_ROOT", "SKEL_Pelvis", "SKEL_L_Thigh", "SKEL_L_Calf", "SKEL_L_Foot", "SKEL_L_Toe0", "SKEL_R_Thigh", "SKEL_R_Calf", "SKEL_R_Foot", "SKEL_R_Toe0", "SKEL_Spine_Root", "SKEL_Spine0", "SKEL_Spine1", "SKEL_Spine2", "SKEL_Spine3", "SKEL_L_Clavicle", "SKEL_L_UpperArm", "SKEL_L_Forearm", "SKEL_L_Hand", "SKEL_L_Finger00", "SKEL_L_Finger01", "SKEL_L_Finger02", "SKEL_L_Finger10", "SKEL_L_Finger11", "SKEL_L_Finger12", "SKEL_L_Finger20", "SKEL_L_Finger21", "SKEL_L_Finger22", "SKEL_L_Finger30", "SKEL_L_Finger31", "SKEL_L_Finger32", "SKEL_L_Finger40", "SKEL_L_Finger41", "SKEL_L_Finger42", "SKEL_R_Clavicle", "SKEL_R_UpperArm", "SKEL_R_Forearm", "SKEL_R_Hand", "SKEL_R_Finger00", "SKEL_R_Finger10", "SKEL_R_Finger11", "SKEL_R_Finger12", "SKEL_R_Finger20", "SKEL_R_Finger21", "SKEL_R_Finger22", "SKEL_R_Finger30", "SKEL_R_Finger31", "SKEL_R_Finger32", "SKEL_R_Finger40", "SKEL_R_Finger41", "SKEL_R_Finger42", "SKEL_Neck_1", "SKEL_Head", "mover" ) fromToBones = #(--this will be a dynamically generated 2d array containing the original bone (such as a roll bone) and what its weight will be moved to #(), --this will contain the initial bone #() --this will contain the bone to move weights to ) skinModBones = #() vertSkinValues = #() boneNames = #() --get the skinned verts for a mesh (theMesh) and add them to the vertSkinValues array fn buildSkinDataArray theMesh = ( print ("Getting vertex skin weights from " + theMesh.name) vertSkinValues = #() vertCount = skinOps.getNumberVertices theMesh.modifiers[#skin] for x=1 to vertCount do ( vertArray = #() BNumber = skinOps.getVertexWeightCount theMesh.modifiers[#skin] x for i = 1 to BNumber do ( boneID = skinOps.getVertexWeightBoneId theMesh.modifiers[#skin] x i boneName = skinOps.GetBoneName theMesh.modifiers[#skin] boneID 0 boneWeight = skinOps.getVertexWeight theMesh.modifiers[#skin] x i tempArray = #(boneID, boneName, boneWeight) append vertArray tempArray ) append vertSkinValues vertArray ) print ("vertex skin weights grabbed from " + theMesh.name) --now im gonna try something funky and check if the bones in the array are bones to remove and if they are then i'll change them to the toBone )--end vertSkin --check the vert weights for the bone we want to remove (fromBone). If found, we add the weight on the the parent bone (toBone). fn replaceWeights fromBone toBone = ( toBoneId = findItem skinModBones (getNodeByName toBone) -- loop through all the verts in the object for vertNoArray=1 to vertSkinValues.count do --for every vert do ( -- Get the influence data for each vert currentVertData = vertSkinValues[vertNoArray] weightToMove = 0 for vertBoneArray=1 to currentVertData.count do --for every weight do ( if fromBone == currentVertData[vertBoneArray][2] do ( addedWeight = false weightToMove = currentVertData[vertBoneArray][3] --lets check the other weights on this vert for a match with our parent bone for recheckVertBoneArray=1 to currentVertData.count do ( if currentVertData[recheckVertBoneArray][2] == toBone do ( -- If we have a match, then the destination bone already exists, create a composite weight weightToAdd = currentVertData[recheckVertBoneArray][3] weightToWrite = weightToAdd + weightToMove currentVertData[recheckVertBoneArray][3] = weightToWrite -- set parent to new weight currentVertData[vertBoneArray][3] = 0 -- clear child weight addedWeight = true -- set the flag to say we've created an updated weight set. )--end add weight loop ) -- what if we didn't find a good parent bone? -- we need to kill the dirty child and repalce it with the correct parent if addedWeight != true do ( currentVertData[vertBoneArray][2] = toBone addedWeight = true )--end new bone and weight loop )--end found toBone loop ) ) )--end replaceWeights fn prepBoneNames geo = ( boneNames = #() selBoneCount = skinOps.GetNumberBones geo.modifiers[#Skin] --get the bone name order for sb=1 to selBoneCount do ( singleBoneName = skinOps.GetBoneName geo.modifiers[#Skin] sb 0 append boneNames singleBoneName ) ) --update the skinning on the LOD mesh using our filtered vertSkinValues array fn updateLODSkin theMesh = ( meshName = theMesh.name for vertNum = 1 to vertSkinValues.count do ( tempBoneArray = #() tempWeightArray = #() for affectingBones=1 to vertSkinValues[vertNum].count do ( boneID = findItem boneNames vertSkinValues[vertNum][affectingBones][2] append tempBoneArray boneID append tempWeightArray vertSkinValues[vertNum][affectingBones][3] ) theVert = vertNum theSkin = theMesh.modifiers[#skin] boneArray = tempBoneArray weightArray = tempWeightArray --skinOps.unNormalizeVertex theskin theVert true skinOps.ReplaceVertexWeights theskin theVert boneArray weightArray --skinOps.unNormalizeVertex theskin theVert false ) print ("skinning updated on " + theMesh.name) )--end updateLODSkin fn findBoneRecursive currentBone = -- Find a bone recursively if needed, iterate up the parent tree to find a bone which exists within the bonesToKeep array ( foundResult = findItem bonesToKeep currentBone.Name if foundResult != 0 then ( -- found the bone in the bonesToKeep array so return it return currentBone print (currentBone.Name+" doesnt need changing") ) else ( -- did not find the bone, so search for its parent return findBoneRecursive currentBone.parent print ("found that") ) ) fn checkSkinBones = --find the bones in skin mod and see if they are toi be kept and if not record what their replacement will be ( print "starting checkSkinBones" for i = 1 to skinModBones.count do --now add data of original bone plus its final bone into a paired array ( myBone = findBoneRecursive skinModBones[i] -- print myBone.name as string -- This is the upmost parent which is in the bonesToKeep array -- print ("Appending "+sceneBones[i].name+" into fromToBones ["+(i as string)+"][1] array") append fromToBones[1] skinModBones[i].name --put in the original bone -- print ("Appending "+myBone.name+" into fromToBones ["+(i as string)+"][2] array") append fromToBones[2] myBone.name --put in the bone we need to move the weight to ) print "fromToBones array built" ) fn buildSkinModBoneList geo = --query all bones in the skin modifier and put them into a array so we can loop trhu them ( skinModBones = #() --ensure its empty noOfBones = skinops.getNumberBones geo.modifiers[#Skin] for b = 1 to noOfBones do --build the array of bones in the skin modifier ( boneName = skinOps.GetBoneName geo.modifiers[#Skin] b 1 realBoneObj = getnodeByName boneName appendIfUnique skinModBones realBoneObj ) print "buildSkinModBoneList done." ) fn runReplaceWeight geo = --using the fromToBOnes array call Stews replaceWeight script ( tmpSel = selection as array -- Use selection.count here Matt -- selection[1] will also return the first item in a selection if tmpSel.count == 1 then ( if geo.modifiers[#Skin] != undefined then ( max modify mode modPanel.setCurrentObject geo.modifiers[#Skin] buildSkinDataArray geo --build an array of all the verts in the mesh buildSkinModBoneList geo --generate an array of all bones in the skin modifier checkSkinBones() print ("fromToBones count = "+(fromToBones[1].count as string)) for i = 1 to fromToBones[1].count do ( -- compare the data in both arrays, if they do not match we need to flip. if fromToBones[1][i] != fromToBones[2][i] then ( replaceWeights fromToBones[1][i] fromToBones[2][i] --create arrays of the new weighting data prepBoneNames geo updateLODSkin geo --now we have the arrays setup do the actual skin weighting ) ) print ("Weight switching complete") ) else ( messagebox ("WARNING! Selection "+geo.name+" has no skin modifier!") beep:true ) ) else ( messagebox ("WARNING! Please run on just one mesh") beep:true ) ) clearListener() runReplaceWeight $