I have not yet isolated which method of SkinOps is broken, but I spent around 4 days in the last two weeks trying to troubleshoot a script problem in Max 2014 that turned out to be wasted time. My code wasn't broken... because I reverted back to Max 2013 to test the code that had been working all along and it works.
I have to delve into it to find out specifically which method is broken, but essentially it is one of these methods:
skinOps.GetVertexWeightBoneID
or
skinOps.GetBoneName
My bet goes to skinOps.GetBoneName because of the integer you pass to determine the bone name based on the bone listed in the Skin UI or the parent bone ....
Will test more later today when I have time to figure out which it is.
In either case, if others can test this in Max 2014 with a bonesystem applied to a skin mod... and if having same problem... PLEASE report the bug to AD.
It is definitely a BUG in skinOps.GetBoneName
I'm attaching a MAXScript that demonstrates the problem.
Running this script provides this info for a model in Max 2013:
Skin:Skin
###############
Vertex: 1
Nth Bone Id: 1
System Bone ID: 4
Bone Name: Bone021
###############
Vertex: 2
Nth Bone Id: 1
System Bone ID: 3
Bone Name: Bone020
###############
Vertex: 3
Nth Bone Id: 1
System Bone ID: 4
Bone Name: Bone021
###############
Vertex: 4
Nth Bone Id: 1
System Bone ID: 3
Bone Name: Bone020
###############
Vertex: 5
Nth Bone Id: 1
System Bone ID: 2
Bone Name: Bone019
But the same model and script does this in Max 2014:
Skin:Skin
###############
Vertex: 1
Nth Bone Id: 1
System Bone ID: 4
Bone Name: BoneM00
###############
Vertex: 2
Nth Bone Id: 1
System Bone ID: 3
Bone Name: Bone028
###############
Vertex: 3
Nth Bone Id: 1
System Bone ID: 4
Bone Name: BoneM00
###############
Vertex: 4
Nth Bone Id: 1
System Bone ID: 3
Bone Name: Bone028
###############
Vertex: 5
Nth Bone Id: 1
System Bone ID: 2
Bone Name: Bone026
I'm attaching a zip file with a sample scene with four random test objects using Skin to demonstrate the problem.
bonename = skinops.getBoneName skinmod bid 1
=> (YOU WILL NEED SORT A LIST OF BONE IN 2014)
numBones = skinops.getnumberbones skinmod
for i = 1 to numBones do
(
append boneArray (skinops.getbonename skinmod i 1)
)
sort boneArray
AND
name = boneArray[bid]
Thank you for that input. Since this is not documented in the MAXScript docs and is a major change in how skinops works form the past, this is definitely a bug.
I will test your suggestion tonight and hopefully it works. But I hope AD reverts to the documented results soon... as I really hate making if... then blocks checking for appversions, etc. It reminds me of Web development in 1999 and worrying about IE4, Netscape navigator and random Joe.
Oke, it works as far we can see. But the default sorting of 3ds Max does something special with case-sensitivity.
We fixed that with a custom sorting, so that case-sensitivity is used:
[code]
fn sortFix s1 s2 = stricmp s1 s2
qsort mybones sortFix
--where mybones is the list of bones.
[/code]
I didn't take the time to investigate. What is the special sorting that you are talking about?
Let's hope this is simply erased in a hot fix or service pack.
So finally it will sort the list without case-sensitivity. Like this:
a, A, b, B instead of a, b, A, B (this is how the default sort function works)
What you need is an a-A-b-B-c-C sorting.
Sorry for the the misunderstanding. English is not my first language.
When the list box became sorted, it caused some inconsistencies. From the subdoc that attempted to fix these inconsistencies:
It seems like the new changes to allow sorting of bone names in the skin
modifier's bones list have broken the getBoneName function.
The bone name returned is using the item number in the UI bones list and
not the actual bone id. skinOps.getVertexWeightBoneId is also affected by this.
This behavior is not compatible with older behaviour, and doesn't make sense - it doesn't make sense that if the user changes the order of the list in the UI, the returned bone id would change.
Loading envelopes from ascii file using the save/load functionality in the advanced parameters rollout (when using .envAscii) also doesn't work, and seem to be the result of the same behavior.
Per the description in MAXX-6725 and the comment in line 249 of CommandModes.cpp, nn skinOps.GetBoneName <Skin> <bone_integer> <nameflag_index>,
the second parameter bone-integer should be bone id not the id in the list box.
In the Max2011, there is no sort in the list box and the bone id is corresponding about the id in the list box.
But in the Max2012, the list box is sorted at the beginning of adding bones. so the bone id does not correspond with the id in the list box.
Here we give two implementation: getBoneName and getBoneNameByListID. The former one is acoording to the bone id and the last one is acoording to the id in the list box
So, since skinOps.getVertexWeightBoneId returns the list box id, you should use skinOps.getBoneNameByListID to get the associated name.
I'm checking now whether there should be a skinOps.getVertexWeightBoneID and a skinOps.getVertexWeightBoneListID. However adding getVertexWeightBoneListID and changing what is returned by getVertexWeightBoneID at this point would add a whole new layer of confusion when trying to use these methods in scripts that support multiple versions.
Larry
I'm checking to see whether the skipOps getVertextWeightBoneID method should be changed to return the bone sys id rather than the list id.
However, if you want your script to support 2014, then some sort of version checking is needed one way or another. Here is the simplest check:
skinops_getBoneNameByListID = skinops.getBoneName
if (hasProperty skinops #getBoneNameByListID) do
skinops_getBoneNameByListID = skinops.getBoneNameByListID
name = skinops_getBoneNameByListID theBone which
Larry
Great thanks for such a beautiful explanation!!!
I know that the Autodesk online help's hiding a lot of good features, but how can they skip so important details?!
They can't even figure out why SkinOps.GetBoneName doesn't return the bone node instead of its name, when <nameflag_index> = 0:
"If nameflag_index = 0 the node that holds the transform for this bone is returned; = 1 the name that exists in the list box is returned."
I don't know if it's a MXS bug(which must be fixed), or just a help page inaccuracy(which must be just deleted).
Well that extra integer ( 0|1) isn't really the problem. The value of skinops.getBoneName no longer returns the same values it used to regardless of passing 0 or 1. In my opinion this is really a bug plain and simple. For the moment this thread gives work arounds at least.
Can't find what you're looking for? Ask the community or share your knowledge.