Announcements

Between mid-October and November, the content on AREA will be relocated to the Autodesk Community M&E Hub and the Autodesk Community Gallery. Learn more HERE.

Problem getting blendshape target index by name

Problem getting blendshape target index by name

mostly_human
Advocate Advocate
924 Views
3 Replies
Message 1 of 4

Problem getting blendshape target index by name

mostly_human
Advocate
Advocate

I am trying to create a procedure that will return the index of a blendshape target, not sure what I am doing wrong. It never finds a match.

 

global proc int GetBlendShapeIndex(string $blendShapeNode, string $targetName) 
{
string $bsAttrs[] = `listAttr -k $blendShapeNode`;
for ($bsAttrName in $bsAttrs) 
{
if (`match $bsAttrName ($blendShapeNode + ".weight[*]." + $targetName)`) {
string $tokens[] = `tokenize $bsAttrName "."`;
int $targetIndex = $tokens[size($tokens)-2];
return $targetIndex;
}
else
error ("Blendshape target \"" + $targetName + "\" not found on node \"" + $blendShapeNode + "\".");
}
}

 

0 Likes
Accepted solutions (1)
925 Views
3 Replies
Replies (3)
Message 2 of 4

Kahylan
Advisor
Advisor
Accepted solution

Hi!

 

Here is a list of mistakes in your code:

 

1) You are addressing attributes by a non existing name. Targetattributes in blendshapes are called .w[0], .w[1] and so on. They are just aliassed to look like the name of the target. Your match command will never find a hit.

2) Your error statement is in the else statement of the if inside the loop. So if the first item in your list isn't a match it will always throw an exception and not look at any other items. You need to take the errorstatement out of the loop

3) If you would find a match like this you wouldn't end up with the index, but rather with a string that contains the index (e.g "weight[15]"), this isn't a great format to continue in. so you would need to further tokenize and convert your string into an integer.

 

Ok, so here is how I would fix this:

global proc int GetBlendShapeIndex(string $blendShapeNode, string $targetName) 
{
string $bsAlias[] = `aliasAttr -q $blendShapeNode`;

for($i=0; $i < size($bsAlias); $i++)
{
if ($targetName == $bsAlias[$i]) {
string $targetName = $bsAlias[$i+1];
string $token[];
int $tknum = tokenize($targetName, "[", $token);
tokenize $token[size($token)-1] "]" $token;
int $tgtIndex = (int)$token[0];
return $tgtIndex;
break;
}
}
error ("Blendshape target \"" + $targetName + "\" not found on node \"" + $blendShapeNode + "\".");

}

I used "aliasAttr" instead of "listAttr", this command will give you an Array of all the aliassed attributes followed by their real names. So you just need to find the alias that is called the same as your target name and then take the next item out of the array.
I took the errorstatement out of the loop, it now runs if the loop finishes without returning out of the procedure.

I also used tokenize and dataconversion to just return the integer of the weightindex. If you want your index to be formatted as "weight[index]" you can delete lines 8-11 and return $targetName instead.

 

I hope it helps!

 

Message 3 of 4

mostly_human
Advocate
Advocate

oh man... i messed that one up hard.  Thank you so much, I clearly see the issues now! *facepalm*

0 Likes
Message 4 of 4

Kahylan
Advisor
Advisor

It happens. Aliassed Attributes are great to help the user keep track of what is going on but they are a bit confusing when adressing them with code...

Have a nice day 🙂

 

0 Likes