[Closed] Strange parentheses issue with my script
I wrote a script that allows the user to work with an object’s bezier handles without going to the sub object level. It works fine as long as the code remains at the top level (i.e. in global scope), but as soon as I stick parenthesis around the script it works incorrectly. I can’t figure out why. I even tried declaring every variable inside the parentheses as global to see if that would fix the problem, but it still didn’t work right.
I must be missing something. Any takers on this?
Here’s a look at the results with and without the parentheses:
And the code (opening and closing parentheses commented out…):
--(
s = $
struct objSet (theObject, ctrl, pointSet, vecSet, lineSet)
animateVertex s #all
rotS = s.rotation; s.rotation = (quat 0 0 0 1)
obj = execute (s.name + " = objSet theObject:$" + s.name)
ctrl = point pos:s.pos wireColor:(s.wireColor) constantScreenSize:true size:10 box:false cross:true name:(s.name + "_CTRL")
obj.ctrl = ctrl
splineIK = Spline_IK_Control(); addModifier s splineIK
splineIK.createHelper (numKnots s)
splineIK.noLinking()
obj.pointSet = splineIK.helper_list
obj.vecSet = #()
obj.lineSet = #()
for i = 1 to (numKnots s) do
(
setKnotType s 1 i #bezierCorner
obj.pointSet[i].name = s.name + "_helper_" + i as string
obj.pointSet[i].wirecolor = color 255 0 0
obj.pointSet[i].constantScreenSize = true
obj.pointSet[i].size = 3
obj.pointSet[i].parent = ctrl
inVec = point pos:(getInVec s 1 i) wirecolor:(color 0 255 0) constantScreenSize:true size:3 box:true cross:false name:(s.name + "_helper_" + i as string + "_in") transform:ctrl.transform
outVec = point pos:(getOutVec s 1 i) wirecolor:(color 0 255 0) constantScreenSize:true size:3 box:true cross:false name:(s.name + "_helper_" + i as string + "_out") transform:ctrl.transform
inVec.parent = obj.pointSet[i]
outVec.parent = obj.pointSet[i]
append obj.vecSet #(inVec, outVec)
inLine = splineShape pos:obj.pointSet[i].pos wireColor:(color 255 255 0) name:(s.name + "_handle_" + i as string + "_in")
addNewSpline inLine
addKnot inLine 1 #corner #line obj.pointSet[i].pos; addKnot inLine 1 #corner #line inVec.pos
updateShape inLine; animateVertex inLine #all
outLine = splineShape pos:obj.pointSet[i].pos wireColor:(color 255 255 0) name:(s.name + "_handle_" + i as string + "_out")
addNewSpline outLine
addKnot outLine 1 #corner #line obj.pointSet[i].pos; addKnot outLine 1 #corner #line outVec.pos
updateShape outLine; animateVertex outLine #all
inLine.parent = obj.pointSet[i]; inLine.showFrozenInGray = false; inLine.isFrozen = true
outLine.parent = obj.pointSet[i]; outLine.showFrozenInGray = false; outLine.isFrozen = true
append obj.lineSet #(inLine, outLine)
)
for i = 1 to (numKnots s) do
(
hn = obj.pointSet[i].name
theType = (getsubanimnames s[#modified_object])[2]
inCtrl = obj.vecSet[i][1].transform.controller[#Position]
inBez = s[#Modified_Object][theType][#Master][(i * 3) - 2]
inLineEnd = obj.lineSet[i][1][#Object__Editable_Spline][#Master][5]
paramWire.connect inCtrl inBez ("in coordsys $" + obj.ctrl.name + " Position + $" + hn + ".pos")
paramWire.connect inCtrl inLineEnd ("Position")
outCtrl = obj.vecSet[i][2].transform.controller[#Position]
outBez = s[#Modified_Object][theType][#Master][i * 3]
outLineEnd = obj.lineSet[i][2][#Object__Editable_Spline][#Master][5]
paramWire.connect outCtrl outBez ("in coordsys $" + obj.ctrl.name + " Position + $" + hn + ".pos")
paramWire.connect outCtrl outLineEnd ("Position")
)
ctrl.rotation = rotS
s.showFrozenInGray = false; s.isFrozen = true
clearSelection()
--)
Okay, I’m not even remotely sure why, but replacing the lines
splineIK = Spline_IK_Control(); addModifier s splineIK
splineIK.createHelper (numKnots s)
splineIK.noLinking()
obj.pointSet = splineIK.helper_list
with
addModifier s (spline_IK_Control())
s.modifiers[#Spline_IK_Control].createHelper (numKnots s)
s.modifiers[#Spline_IK_Control].noLinking()
obj.pointSet = s.modifiers[#Spline_IK_Control].helper_list
seems to have done the trick. I guess I would want it set up like that anyway if I’m going to be working with multiple shapes, so… 2 birds one stone I suppose. Still, very strange shrugs
(By the way, even though it’s working now, I’d really like to know WHY this happened so that I can avoid it in the future. Any guesses?)
When run in the Listener or in the global scope as you did here, each line of the script is more or less its own expression. Each of these expressions is run individually and creates its own Undo record (look in the Undo list after running without parentheses and you will see). In this mode, the UI is updated after each expression, so adding a modifier, then doing other things has no side effects.
When you add the parentheses, the whole code becomes one large block running in its own local scope and creating ONE Undo record. While it is running, some implicit UI updates like the refreshing of the modifier stack and the viewports might be suppressed until the Undo record is committed, and in your case this seems to cause some data to be in a wrong state.
In your particular case, adding a ‘max modify mode’ to the beginning of the script will cause the Modify tab of the Command panel to be active while the script is running and will allow the correct update of the spline data and its modifiers which is otherwise suppressed if in creation mode. Your original code seems to work for me if I switch to Modify tab manually before running it, and by adding the line to switch explicitly it should always work.
If that does not solve the problem for you, let me know.
Thanks Bobo, it makes a lot more sense when I look at it from that perspective. I guess I should have realized that Max works that way, since I’ve noticed that the undo command works according to the parentheses blocks, and I’ve also had issues with UI updates. Anyway, I’ve got a working solution for that problem.
Do you think you might have any advice regarding my other problem with the script, mentioned at http://forums.cgsociety.org/showthread.php?f=98&t=892892 ?
(Sorry to be using 2 threads for the same script, but as you can see it’s for a different issue…)