-
Notifications
You must be signed in to change notification settings - Fork 36
Description
This bit me recently.
node = cmdx.createNode("translate")
node["translateX"] = 5
node["translateY"] = 5
node["translateZ"] = 5
with cmdx.DagModifier() as mod:
mod.setAttr(node["translate"], 0)What value do you expect translate to have?
[0, 0, 0]?[5, 5, 5]?[5, 0, 0]?[0, 5, 5]?[15161353, 135135136425, 63513]?
That's right! The numbers will be garbage!
What happened?
Here's what the underlying code looks like.
if isinstance(value, int):
mod.newPlugValueInt(mplug, value)Where value is what you gave the modifier, in this case 0. 0 is an integer, which would prompt a call to MDGModifier.newPlugValue(). Notice how it has Int int its name? Whatever value you give it, it will assume that it is an int. An int has a pre-defined number of bytes, so what Maya will do here is reach into your int for that number of bytes, even though the actual attribute needs many more bytes than that, as it is a compound attribute. translateX, Y and Z.
So, translateX migth be given the correct value, but the remaining values would get garbage. You didn't pass enough bytes, it would likely try and reach into memory it doesn't own and assign that. Resulting in gibberish values, possibly random, possibly random unless that space in memory is occupied by something else, like a YouTube video or whatever.
How do I solve it?
Make sure you pass enough data. Maya will not tell you whether or not you did, you'll have to know what you are doing.
# Alternative 1
with cmdx.DagModifier() as mod:
mod.setAttr(node["translateX"], 0)
mod.setAttr(node["translateY"], 0)
mod.setAttr(node["translateZ"], 0)
# Alternative 2
with cmdx.DagModifier() as mod:
mod.setAttr(node["translateX"], [0, 0, 0])Future Work
Normal attribute setters account for this.
node = cmdx.createNode("transform")
node["translate"] = 5This figures out that you meant (5, 5, 5) because translate is a compound of 3 children.
We could address this for modifiers in the same way. If it's a Vector3, and you've passed a single int, convert that int to 3 floats. It would come at a performance cost (likely from querying of the attribute type), so we could put it behind a safe=True that defaults to True and enables the user to optimise by disabling it.