I hate the curveControl UI!!!

Hi, can anyone help me on this?

I put a curveControl UI item in a custom attribute applied to a Morpher modifier.

Then I put a script controller on a morph target so it can be governed by the curveControl. It all works fine until I close and re-open Max, and re-open the scene.

When I reopen the scene the script controller starts complaining that the curveControl is undefined.

I've tried pre-loading the curveControl's properties using the "on load do" handler but again, none of the curveControl's properties become valid until you physically click on the object and go to the modify panel containing the curveControl. Once the curveControl is visible you can re-evaluate the script controller and everything works fine again.

It is DRIVING ME INSANE! There has to be a way to load and access the properties before the curveControl is visible. This thing is the WORST!


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Anubis's picture

Reply to the last on top

In fact the rollout ui controllers that can be linked to the parameter block types is limited to: spinner, slider, radioButtons, checkbox, checkbutton, Colorpicker, pickButton, mapButton, materialButton. Yes, the CurveControl is not one of them, and that w'd not be fatal if the Script Controllers recognize the CAs/plugins rollouts. I face this issue for a first time. Bug or not, its for sure is critical disadvantage of Script Controllers. In other words, we can hit that limitation in other ui items, not only with CurveControl. What a shame...

Now on the last reply...
I was thought that the SC executed too early, but as you said that floater fix startup errors, I thought that forced mod-panel + modifier selection (in "on load do") should be acceptable fix (w/o floater).

max modify mode
modPanel.setCurrentObject $box01.morpher

Another thought going in my head... It sounds sensibly or at least worthy to be tested. So, if you move the whole function and it result to the CAs, and add a float parameter to the parameter block which to hold just the result of the function. Then create a variable in the SC and associate with that parameter. That should work?...

my recent MAXScripts RSS (archive here)

pacermike's picture


Ok, I see what you're saying.

On your first idea. I will try that in place of the floater and see if "selecting" the object in the "on load do" handler will essentially pre-initialize it. The real test will be to see if that works when there are more than one unique instance of the CA in the scene.

For your second idea, that makes sense. The problem with my function though is that it doesn't seem to solve as quickly as the getValue CC method. I got it working, but only while manually moving the Time Slider, and it was noticeably choppier than getValue. I think I could do what you're saying and have the SC reference the function only when/if the getValue method suddenly becomes undefined, like during a CA redefine operation for example. Like an emergency backup.

I'm going to try your first idea first and see what happens.

pacermike's picture

Hey again,

I tried:

max modify mode
modPanel.setCurrentObject $box01.morpher

and it still can't find the curve. Now I'm really confused because the CC is visible straight from the start and the script controller STILL doesn't recognize it. Maybe I could try a notifyDependents or something? But I'm still not totally sure how to use those functions with CA's.

Anubis's picture

Uh, my Max crash on loading

Uh, my Max crash on loading the scene file. I'm on Max 2009. The script looks fine. I guess that "on load do" should work, but I see you used it and still has a problem. Did you try "on postLoad do"?

my recent MAXScripts RSS (archive here)

pacermike's picture


I should've specified that the file was created in Max 2010. Sorry about that. Here's a version made in Max 9.0. Should open in 2009 I think.

I'll give postLoad a shot and see if that helps at all. I have a feeling it has something to do with the visibility of the curveControl UI. I wish Autodesk would make this UI a little friendlier. It's a beast to work with.

morphscript_testscene_loadtest_v9.max 368 KB
Anubis's picture

yep, the CC is a pain, but

yep, the CC is a pain, but the problem here looks more deeper... if type to the Listener (even before open the CA's rollout): "$box01.morpher.morphTools.xyzSplit" Max print: Rollout:xyzSplit that means it recognize the rollout, but in the script controller Max say: -- Unknown property: "xyzSplit" in "$Box01.modifiers[#Morpher].morphTools". odiously...

my recent MAXScripts RSS (archive here)

pacermike's picture


I noticed that too! I have no clue how it's even possible for it to be valid one second and then unknown the next. Any ideas?

Anubis's picture

well, i think this must be

well, i think this must be reported as bug to Autodesk.

P.S. - I need to go, but I have one idea in mind to test...
put your script expression "(getValue ...)*100" in a global variable into "on load do", and add to the script controller only the variable name.

my recent MAXScripts RSS (archive here)

pacermike's picture


I'll give the global variable a try.

The other thing I was thinking of was taking the curve data that I stored in the param block as a string and calculating the curve without using the CC at all.

I'll post back if I have any luck with either approach. Thanks again for your help :)

pacermike's picture

OK, forget the curveControl

I think it is hopeless to try and use the getValue method of the curveControl to drive anything reliably using a script controller.

However, since I have the CC writing to an array which I'm storing as a string in the param block I have all the data I need whether I have access to the CC or not.

I wrote this code which takes the four points of a bezier segment (point1, point1 out-tangent, point2 in-tangent, and point2) and a given X-coordinate (xVal) and returns the Y-coordinate of the point on the curve!

fn bezierYval p0x p0y p1x p1y p2x p2y p3x p3y xVal =
	local c = 3 * ([p1x, p1y] - [p0x, p0y])
	local b = 3 * ([p2x, p2y] - [p1x, p1y]) - c
	local a = [p3x, p3y] - [p0x, p0y] - c - b
	local d = [p0x, p0y]
	-- finds approx. percentage along curve where curve point x coordinate is approx. equal to xVal 
	percent = for r = 0 to 1.0 by .001 where \
	(a * ((r * r) * r) + b * (r * r) + c * r + d).x >= xVal - .001 and \
	(a * ((r * r) * r) + b * (r * r) + c * r + d).x <= xVal + .001 collect r
	-- finds the average of the percent array
	sum = 0
	for i = 1 to percent.count do sum = sum += percent[i]  
	avgSum = sum / percent.count 
	r2 = avgSum * avgSum
	r3 = r2 * avgSum
	-- uses avgSum to find [x, y] coordinate of curve where x coordinate is approx. equal to xVal 
	newPoint = a * r3 + b * r2 + c * avgSum + d
	-- returns just the y coordinate since x is already know (the xVal variable entered in to the function)

If I run the function using my curve values I get:

bezierYval 0 0 (0.862031 + 0) (0 + 0) (-0.605639 + 1) (0 + 1) 1 1 .5 = 0.24559

This is the same value that the curveControl method getValue returns, so my function works...

BUT! I don't know how to get a scripted function to work inside a script controller. The help files say you can use scripted functions in a script controller but so far all I get are errors.

Any ideas or examples?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.