Which controller uses its own value in expression(calcualting new value)?


#1

Hi!

Is there are a controller which will use its own value in an expression?
For example the value of the controller is set to 25. The controller will execute this expression:

result = degToRad(controllerValue)

and the result will be passed to the parameter to which the controller is linked.

Linear_Float does not allow me to add an expression.
Float_Script and Float_Expression allows expression, but how to use the controller’s own value?


#2

What I have so far:

Float Expression controller with expression degToRad(myValue) is linked to the parameter I want.
the myValue is assigned to a Float List controller.
Linear Float controller is linked to that Float List controller.

Ugly, but works. Entering 34 in the Linear Float is translated correctly to the desired parameter.

I hope there is more elegant solution.


#3

Hmm… that sounds like a “circular dependency”. I’m sure you should solve the problem differently.
Could you please explain the desired “setup” more clearly?


#4

Now I have this:

This is the only way I have found so far. The Linear Float controller value is used as Horizontal rotation value for the bitmaps. To make it to work correctly the Weight of the “Controller #2” is set to 0. It works on max2020, but it max2022 the script I wrote gives an error(will check it again tomorrow). And this way of using the controllers has one drawback - I have to double click the Float Expression controller so the value, set in the Linear Controller to be updated and set to the Horizontal rotation parameter.

The previous solution(described in my post above) which looks this way:


also work, but only the Float Expression controller is linked to the map and when the “Lay Out All” is used the Linear Float controller goes away from the map it has to “control”.

The desired setup should look(if possible) this way:

Where the Float Expression is a controller which can take its own value as a variable. The “rot” variable has to be the value, set in the FE controller’s spinner, so I can set the value to 25 and the Horizontal Rotation of the map will be set to 25 also(because the controller will evaluate the degToRad(rot)). But I can’t find a controller which can do this.


#5

I think you’re overcomplicating things… for example, here are two solutions (and there are others):


delete objects

rot = dummy name:#rot 
rot.rotation.controller = Euler_XYZ()

---- #1
sp1 = geosphere name:#sp1 radius:0 wirecolor:green pos:[0,50,0]
paramWire.connect rot.rotation.controller[#Z_Rotation] sp1.baseObject[#Radius] "radtodeg(abs Z_Rotation)"

---- #2
sp2 = geosphere name:#sp2 radius:0 wirecolor:orange pos:[0,100,0]
rad_rot = sp2.radius.controller = float_expression()
rad_rot.addscalarconstant #rad_convert (180.0/pi)
rad_rot.addscalartarget #deg rot.rotation.controller[3].controller
rad_rot.setexpression "abs(deg) * rad_convert"

#6

I guess your problem is that you want to use a rotation controller or its leaf (x, y or z) which is in radians, but the target value is in degrees. Both of the above methods do the conversion.


#7

Thank you, Denis.

Most probably I do.
I need a controller which will work in SME. The setup should be like in the last image in my previous post - one controller, linked to as many mats/maps I want. When I alter the value of this controller, the controller will do some math with this value and will feed the linked parameters with the new value. Basically, it should look like this:

No matter what I do the spinner in the Float Expression controller is not accessible. I can’t set its value manually. It only shows the value of the evaluated expression.


#8
MCCA = attributes MCCA attribid:#(122112,133113)
(
	parameters params 
	(
		master_value type:#float
	)
)
ca = createinstance MCCA
mc = ca.master_value.controller = bezier_float()

sme.Open()
(
	--try(sme.DeleteView 2 off) catch()
)
k = sme.CreateView "Multiuse"
vw = sme.GetView k
vb = createinstance VRayBitmap

bc_vnode = vw.CreateNode mc [0,10] 
vb_vnode = vw.CreateNode vb [200,10]

paramWire.connect ca[#master_value] vb[#Horiz__rotation] "master_value * pi / 180.0"

vb.verticalrotation.controller = mc

vw.ZoomExtents type:#all

you can do it without involving a CA, using a SME reference directly, but it will be more complicated and less safe.


#9

Thank you, Denis!

It does work, I have to replace

#Horiz__rotation with #horizontalRotation

Update: it does work for multiple maps.


#10

New question - how to add more mats/maps to the Bezier float controller, created with the code which Denis posted above.
First I select few maps, then I run the code and I have one Bezier float controller which is connected to the selected maps and everything works perfect.

But how to make connections(paramWire) between the same Bezier Float controller and new maps? I can get the controller and maps, I can find the MCCA attribute, but I can’t access the `master_value, so I can’t create new paramWire to the selected maps.

MCCA[#master_value] is not a solution(throws an error No ""get"" function for <AttributeDef:).
If I create an instance of the MCCA then I have new Bezier float controller in SME.


#11

you have to use an instance of MCCA. But you try to use a ca definition.
see my code example:

ca = createinstance MCCA

#12

Hi, Denis!

I am using an instance of the MCCA, but it creates a new Bezier Float controller. It does not link the selected Bezier float controller to the selected maps.
Here is the code:

(
	if SME.isopen() == true then
	(
		v = SME.getView SME.activeView
		smeNodesSelectedArr = #()
		controllerNodeArr = #()
			
		for i = 1 to v.GetNumNodes() where (n = v.getNode i).selected do
		(
			if classOf n.reference == vrayBitmap then
				append smeNodesSelectedArr n.reference
			else
			(
				if classOf n.reference == Bezier_float do
					append controllerNodeArr n.reference
			)	
		)
		
		if controllerNodeArr.count == 1 and smeNodesSelectedArr.count != 0 do
		(
			for attrDef in custAttributes.getSceneDefs() where attrDef.name == #MCCA do
			(
				ca = createinstance attrDef
				for i = 1 to smeNodesSelectedArr.count do
				(
					paramWire.connect ca[#master_value] smeNodesSelectedArr[i][#horizontalRotation] "master_value * pi / 180.0"
				)
			)
		)
	)
)

#13

I think I have found a solution.
After the second BezierFloat controller is created by the code above I select the two controllers and then:

replaceInstances controllerNodeArr[1] controllerNodeArr[2]

In the SME view there are 2 controllers, updating any of them updates the other one, all linked maps are also updated. Saving and reloading the scene and in the SME there is only one controller, linked to all maps.