Accessing bones in the skin modifier via names instead of indices

I would like to use the skinOps interface:

skinOps.GetVertexWeightBoneID <Skin> <vertex_integer> <vertex_bone_integer>

Instead of using the bone’s index (as an integer) for <vertex_bone_integer>, could it be replaced with the bone’s name string(like “Bip01 L Shoulder”)? This will make iteration way more easier.

Any hints or suggestion are gratefully appreciated.

You could create your own lookup that maps the names to the bone id, and then instead of passing in the bone id you could pass in (boneLookup “Bip01 L Shoulder”)

so, essentially an intermediate function which searches the skeletal-hierarchy for the name specified and then passes the index of the found entry to the skinOps function?

My suggestion would be to entirely wrap skinOps into your own struct. So, you’d have another method, “xpecSkinOps.GetVertexWeightBoneIDByName” that would do what you want, and all the needed stuff under the hood. This will make working with skinOps stuff much easier in the future, since it is one of the worst systems in Max.

However it won’t solve your current problem- IIRC the way to do this is to create an array of bone names and then get the index of the name you are looking for (make sure skinMod is in modpanel, but running “modPanel.setCurrentObject skinMod” before hand, where skinMod is your modifier:


struct xpecSkinOpsDef
(
	fn getBoneNames skinMod =
	(
		local cnt = skinOps.getNumberBones skinMod
		for i = 1 to cnt collect skinOps.getBoneName skinMod i 1
	),
	fn getBoneId skinMod boneName =
	(
		findItem (getBoneNames skinMod) boneName
	),
	fn getVertexWeightBoneIdByName skinMod vert boneName =
	(
		skinOps.getVertexWeightBoneId skinMod vert (getBoneId skinMod boneName)
	)
)
global xpecSkinOps = xpecSkinOpsDef()
xpecSkinOps.getVertexWeightBoneIdByName obj.modifiers[#Skin] 1 "LeftKnee"

Thanks for the strcut advice, that’s really helpful.

The two functions (getVertexWeightBoneIdByName() and getVertexWeightBoneId() ) are primarily the methods get used today; and indeed for better further reuse, all the bonename manipulating functions should really be in the struct for life saving.

Since the final goal is to set weights on the new skeleton, there’s a typo in the maxscript help file:


skinOps.SetVertexWeights <Skin> <vertex_integer> ( <vertex_bone_integer> | <vertex_bone_array> ) ( <weight_float> | <weight_array> 

The <vertex_bone_integer> is supposed to be the bone_id, not the bone order index affected in the vertex.