Notifications
Clear all

[Closed] Scripted controller executed twice?

I have a rigging setup where I want a crane to animate based on a controller helper object and/or by input of the rotation and boom values.

The controller helper has a scale_script controller and within that I triggers some logic to set the crane rotation and boom values, however, it seems that this script is being run twice on every movement of the controller.

when I print some values, like a relative position of the controller to the crane base, it prints it’s new position, but also a cached old position:

[19.5136,0,-30]
[50.6494,0,-30]
[19.5136,0,-30]
[51.7331,0,-30]
[19.5136,0,-30]
[53.0577,0,-30]

see the returning old position?

the scale Script I currently have is calculating the boom (up rotation of the crane) value, and I try to put that back in to the custom_attribute value. The slewObject is taking care of the crane rotation in z, but no logic for that yet as I want to get this working first.

craneMod = controlObject.modifiers[#attribute_holder]

--calculate boomAngle
x = 128
z = -20
maxBoom = 82
			
relBoomPos = in coordsys slewObject boomObject.pos
relCtrlPos = in coordsys slewObject controlObject.pos - relBoomPos

print relCtrlPos

d = relCtrlPos.x
l = sqrt((x^2)+(z^2))
a = atan(z/x)

if d > l then 
(
	dd = l-(d-l)
	if dd < x then
	(
		a = 0.0
	)
	else
	(
		a = a - acos(dd/l)
	)
)
else
(
	a = a - acos(d/l)
	if a < -maxBoom then
	(
		a = -maxBoom
	)
)


--craneMod.boomAngle = abs a

--output scale default value to end scale script
[1, 1, 1]

I would like the scripted controller to execute only once while moving the controller and not to output the old position. Is that possible?

4 Replies

To answer your question, I need to see how you set up the script controller and what you are trying to print there.
It’s hard to guess without seeing the code…

Looks like you are getting and setting the value of the same scripted controller but in different time… like trying to get a delta. So the first time you see the print of “on get” and the second time “on set”, because the script controller needs execution in both cases.

Edit: I had a detailed reply about my case, but actually it can be recreated very easilly

create two helpers in an empty scene and add a scale script to one of them. Add both of the helpers as variable nodes in the script controller dialog and reference one of the helper positions in the other helpers coordinate system. Then print that relative position.

the relative position is printed twice on every frameupdate when you move the helper, one new value and one ‘cashed’ value. It does only print once when moving the timeslider, but I’m interested in actual real-time behaviour

so that would explain your “on get” and “on set” behaviour somewhat I guess? Do you know if there is a way to prevent the on-get execution?

edit2: actually it also does it when just printing the postion of the helper containing the scale script…

delete objects

target = point name:#target pos:[0,0,20] wirecolor:orange
source = point name:#source pos:[0,0,0] wirecolor:red

d = dummy name:#dummy boxsize:[2,2,2]

s = d.scale.controller = scale_script()

/*
-- #1:

s.addnode #target target
s.addnode #source source

s.setexpression "v = inverse target.transform * source.transform; format \"DUMMY pos:% time:% \\n\" v F; [1,1,1]"
*/

/*
-- #2:

s.addtarget #target target.controller
s.addtarget #source source.controller

s.setexpression "v = inverse target * source; format \"DUMMY pos:% time:% \\n\" v F; [1,1,1]"
*/

/*
-- #3:

s.addtarget #target target.controller
s.addtarget #source source.pos.controller

s.setexpression "v = source * inverse target; format \"DUMMY pos:% time:% \\n\" v F; [1,1,1]"
*/

/*
-- #4:

s.addnode #target target
s.addnode #source source

s.setexpression "v = in coordsys target source.pos; format \"DUMMY pos:% time:% \\n\" v F; [1,1,1]"
*/

There are several ways how to script what you want … (I showed four, but there are another). As you can see, they all work correctly and as expected (i.e. no double calls).
Using the coordsys context is probably the worst solution in scripted controller expressions (IMHO).

Next time you want to discuss a code or a custom setup, please provide an example scene the scripted way as above, if it’s possible. Or upload a MAX file (preferably in the MAX 2016 version).
This is a standard practice on this forum thread. It allows everyone to work with the same initial data and conditions.
(I personally sometimes just ignore some messages due to the difficulty of reproducing the problem, or a lot of time required for this)

Thanks for showing some alternatives denisT.

for some reason I thought it necessary to put the controller script on the actual object I was moving… This causes the double execution. My guess is that max, while moving objects, max is caching their original position, in order to always give a final offset when you are done moving.

however, putting the scale script on a separate helper gives the clean results I was after.

I’ll be sure to include more info next time Thanks again!