- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I'm writing something to create/save/re-create blendShapes programatically and I would really like to make use of the supportNegativeWeights capabilities. Here's some code to create a quick simple example of what I'm trying to figure out - as well as some odd behavior I'm noticing (this is in maya 2017)
import maya.cmds as mc # create base and 'control' # base = mc.polyCube(n='base', ch=False)[0] ctrl = mc.circle(n='ctrl', nr=(0,1,0), ch=False)[0] mc.addAttr(ctrl, ln='test', at='float', k=True) # create targets # pos10_tgt = mc.polyCube(n='pos10_tgt', ch=False)[0] neg10_tgt = mc.polyCube(n='neg10_tgt', ch=False)[0] mc.xform(pos10_tgt, ws=True, t=(1.5, 0, 0)) mc.xform(neg10_tgt, ws=True, t=(3.0, 0, 0)) mc.move(0, 1, 0, '%s.cp[2:5]' %pos10_tgt, r=True) mc.move(0, -1, 0, ['%s.cp[0:1]' %neg10_tgt, '%s.cp[6:7]' %neg10_tgt], r=True) # create blendShape # bs = mc.blendShape(base, n='test_bs')[0] mc.setAttr('%s.supportNegativeWeights' %bs, 1) mc.blendShape(bs, e=True, t=(base, 0, pos10_tgt, 10.0)) mc.blendShape(bs, e=True, t=(base, 0, neg10_tgt, -10.0)) # alias attr and connect it # mc.aliasAttr('test', '%s.weight[0]' %bs) mc.connectAttr('%s.test' %ctrl, '%s.test' %bs)
Ok, so, here I'm creating a cube and hooking in a positive 10 target and a negative 10 target for the first target index of the blendShape, then driving it with the 'test' attr on a circle. And it works! I have a blendShape with inbetween targets at 10 and -10 and it all works as I would expect (even past 10/-10). I'm doing this instead of a 1/-1 value because I will be using this for some facial controls that will have a 10/-10 range, and it would be really nice to do a direct connection instead of needing a multiplyDivide or multDoubleLinear between the driver plug and the blendShape weight attr... Also, a minor note - 'bs' is what I use for a 'blendShape' variable; it does not stand for 'bullsh**'
One part of the tool I'm writing checks to see if an inbetween already exists if you're trying to add a new one (through the tool). It does this by calculating the inputTargetItem index and checking if it's in the list returned when you run mc.getAttr('%s.it[0].itg[%d].iti' %(bs, target_index), mi=True). I calculate the inputTargetItem index with a helper function that returns this: int((inbetween_value * 1000) + 5000). This works great for everything with an inbetween value of -5.0 up. I also have a corresponding helper function that takes the index value and returns the inbetween value like so: (index - 5000) / 1000.0. This is why anything -5.0 and up works (-5.0 results in an index value of 0)
So in this case, the positive 10 inbetween has an index of 15000 ((10 * 1000) + 5000 = 15000); and I can plug in the index value 15000 to determine the inbetween value of 10 ((15000 - 5000) / 1000.0 = 10). Awesome and expected. But, the negative 10 inbetween index value is -2147478650. I don't know how this number is calculated: (-10 * 1000) + 5000 = -5000 (not -2147478650) and (-2147478650 - 5000) / 1000.0 = -2147483.65 (not -10)
First of all, I didn't even realize you could have a negative index in maya (mind blown on this one). So, does anyone know the formula for calculating the inputTargetItem index for inbetween values < -5? Also, the formula for calculating the inbetween value from a negative index would be nice too (but I could probably figure it out if I had the other...)
Before I close this massive wall of text, there's some odd stuff I've noticed with this too...
- The weight attr does not show up in the channel box for the blendShape until it's connected - not a huge deal since I'm doing this with code and it still works, but I thought it was worth mentioning since it may be a bug... (btw - it does show up if I add a target with a target value of 1).
- If I have the input/output connections of the blendShape pulled up in the node editor and mouse over the circle/dot in front of the negative inbetween's inputGeomTarget attr, maya spits out this error: // Error: line 1: No object matches name: test_bs.inputTarget[0].inputTargetGroup[0].inputTargetItem[-2147478650] //.
- Also, I can list connections from the target world mesh attr and get the corresponding inputGeomTarget on the blendShape, but if I list connections from the inputGeomTarget for the negative target I get an error:
pos_igt = mc.listConnections('%s.worldMesh[0]' %pos10_tgt, p=True)[0] neg_igt = mc.listConnections('%s.worldMesh[0]' %neg10_tgt, p=True)[0] pos_igt # Result: u'test_bs.inputTarget[0].inputTargetGroup[0].inputTargetItem[15000].inputGeomTarget' # neg_igt # Result: u'test_bs.inputTarget[0].inputTargetGroup[0].inputTargetItem[-2147478650].inputGeomTarget' # mc.listConnections(pos_igt) # Result: [u'pos10_tgt'] # mc.listConnections(neg_igt) # ValueError: No object matches name: test_bs.inputTarget[0].inputTargetGroup[0].inputTargetItem[-2147478650].inputGeomTarget #
I'm pretty sure that the -2147478650 index item exists because it is connected and it's returned from listing the connections of the target geometry, so I'm assuming this is a bug...
Thank you for taking the time to read this, and for any help you can provide on that formula!
Solved! Go to Solution.